获取上下文以从命令行 Android 应用程序调用 bindService

问题描述

最近我发现您可以将 Java 代码编译成 DEX(使用 Android API),然后使用 app_process 从 ADB shell 命令行直接执行它,而无需安装 APK。我创建了一个类似于 this one 的示例代码。我编译它,执行它并且它工作了。

然后我想进一步探索,看看我可以从 Android 命令行 Java 使用哪些功能。我想使用一些更高级的 Android 功能,并尝试从我的命令行 Java 应用程序绑定服务(由不同的应用程序导出)。但是,为了调用 bindService,您需要 Context 并且我在获取 Context 时遇到了困难,因为没有活动可以从中获取它。

所以我尝试实现一个更简单的程序,该程序由一个主类组成,该类将消息打印到控制台和日志,然后尝试获取 Context 对象。然后,主类尝试从 ApplicationInfo 对象获取 Context 并打印进程名称。我试图从扩展 Context 的类中获取 Application,但没有成功。

我的代码如下:

// HelloWorld.java

import android.os.Build;
import android.util.Log;
import android.app.Application;
import android.content.pm.ApplicationInfo;
import android.content.Context;

public class HelloWorld {
    
    private static Context mContext;

    public static void main(String[] args) {
        System.out.println("Hello World,API v" + Build.VERSION.SDK_INT);
        Log.e("CMDLINE","HELLLLOOOOO");

        App app = new App();

        mContext = app.getContext();

        ApplicationInfo ai = mContext.getApplicationInfo();

        System.out.println("AppInfo: " + ai.processName);
        Log.e("CMDLINE",ai.processName);
        
    }

    public static Context getContext(){
        return mContext;
    }
}
//App.java

import android.os.Build;
import android.util.Log;
import android.app.Application;
import android.content.pm.ApplicationInfo;
import android.content.Context;

public class App extends Application {
    private Context mCtx;

    public App(){
        mCtx = this;
    }

    public Context getContext(){
        return mCtx;
    }
}

我按照以下方式编译和执行代码

  • 编译 Java:javac -classpath ".:/root/Android/Sdk/platforms/android-30/android.jar" HelloWorld.java App.java
  • 创建 DEX:/root/Android/Sdk/build-tools/30.0.3/dx --dex --output=classes.dex HelloWorld.class App.class
  • 归档输出zip HelloWorld.zip classes.dex
  • 将存档复制到设备:adb push HelloWorld.zip /data/local/tmp/
  • 创建一个起始 script start_java.sh
    #!/system/bin/sh
    
    base=/system
    export CLAsspATH=/data/local/tmp/HelloWorld.zip
    exec app_process $base/bin HelloWorld "$@"
    
  • 将脚本推送到设备,使其可执行:adb push start_java.sh /data/local/tmp; adb shell chmod +x /data/local/tmp/start_java.sh
  • 执行脚本:adb shell /data/local/tmp/start_java.sh

执行后,我得到以下控制台输出

Hello World,API v28
Killed 

ADB Logcat 包含以下内容

02-11 15:54:35.949 31766 31766 D AndroidRuntime: Calling main entry HelloWorld
02-11 15:54:35.950 31766 31766 E CMDLINE : HELLLLOOOOO
02-11 15:54:35.951 31766 31766 D AndroidRuntime: Shutting down VM
--------- beginning of crash
02-11 15:54:35.953 31766 31766 E AndroidRuntime: FATAL EXCEPTION: main
02-11 15:54:35.953 31766 31766 E AndroidRuntime: PID: 31766
02-11 15:54:35.953 31766 31766 E AndroidRuntime: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.ApplicationInfo android.content.Context.getApplicationInfo()' on a null object reference
02-11 15:54:35.953 31766 31766 E AndroidRuntime:    at android.content.Contextwrapper.getApplicationInfo(Contextwrapper.java:159)

这意味着我没有收到来自 ContextApp 对象。我什至尝试将一个小的 AndroidManifest.xml 添加到仅包含以下几行的 ZIP 存档中,以查看系统是否会授予我 Context,但错误没有改变。

<application android:name="App">

</application>

我的问题是:

  • 有什么方法可以欺骗系统为我的命令行应用程序提供一个 Context 对象,以便我可以调用 bindService?我知道有很多与上下文相关的重要事情(权限、文件目录...),但我并不真正需要它们——我可以只使用某种“通用模拟 Context”这样我就可以调用 bindService
  • 有没有什么方法可以在没有 Context 的情况下绑定可以在命令行应用程序中运行的服务?
  • 有什么方法可以从 ADB shell 绑定服务,类似于您如何调用 service call 与您可以使用 service list 显示的系统服务进行通信?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...