Android 靜默安裝/卸載功能實現

原方案在這裏https://zhuanlan.zhihu.com/p/21585970,下面寫具體實現

核心代碼及原理通過adb shell 中的pm指令來操作,主要是通過process去實現命令

           String cmd = "pm install /sdcard/xxx.apk"//寫要執行的命令,卸載爲pm uninstall com.xxx.xxx 
           try {
                if("".equals(cmd)) {
                    throw new NullPointerException();
                }
                String consoleReply = Runtime.getRuntime().exec(cmd).toString();
                return consoleReply;
            } catch (IOException e) {
                e.printStackTrace();
                return MyService.this.ERROR;
            }

運行這段代碼需要system uid標識及系統簽名

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.xxx.xxx"
    android:sharedUserId="android.uid.system">

生成apk後需要系統簽名

java -jar signapk.jar platform.x509.pem platform.pk8 app-release.apk signapp.apk

現在遇到的項目是給系統做的,所以打算使用aidl方式去調用該接口,當然用廣播做也可以

下面是定義aidl的內容,定義了一個接口,和一個運行的方法需要實現

interface AidlShellCmd {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
//    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
//            double aDouble, String aString);

    String runCmd(String cmd);
}

Server端,

MyService.java

public class MyService extends Service {

    public static String ERROR = "ERROR";

    private AidlShellCmd aidlShellCmd = new AidlShellCmd.Stub() {
        @Override
        public String runCmd(String cmd) throws RemoteException {
            try {
                if("".equals(cmd)) {
                    throw new NullPointerException();
                }
                String consoleReply = Runtime.getRuntime().exec(cmd).toString();
                return consoleReply;
            } catch (IOException e) {
                e.printStackTrace();
                return MyService.this.ERROR;
            }
        }

    };

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return aidlShellCmd.asBinder();
    }
}

Client端,

Mainactivity.java

public class MainActivity extends AppCompatActivity implements ServiceConnection, View.OnClickListener {

    private AidlShellCmd aidlShellCmd;

    private Button bt_uninstall, bt_install;

    private String cmd = "";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bt_uninstall = (Button) findViewById(R.id.bt_uninstall);
        bt_install = (Button) findViewById(R.id.bt_install);


        Intent intent = new Intent("com.xxx.xxx");//action
        ComponentName componentName = new ComponentName("com.xxx.xxx", "com.xxx.xxx.MyService");//Server端的Service設置的包名
        intent.setComponent(componentName);
        bindService(intent, this, Context.BIND_AUTO_CREATE);

        bt_uninstall.setOnClickListener(this);
        bt_install.setOnClickListener(this);

    }

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        aidlShellCmd = AidlShellCmd.Stub.asInterface(service);
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        Toast.makeText(this, "onServiceDisconnected", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.bt_uninstall:
                try {
                    cmd = "pm uninstall cc.xxx.xxx";
                    Toast.makeText(this, "1" + aidlShellCmd.runCmd(cmd), Toast.LENGTH_LONG).show();
                    cmd = "";
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                break;
            case R.id.bt_install:
                cmd = "pm install /sdcard/xxx.apk";
                try {
                    Toast.makeText(this, "1" + aidlShellCmd.runCmd(cmd), Toast.LENGTH_LONG).show();
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                break;
        }
    }

    @Override
    protected void onDestroy() {
        unbindService(this);
        super.onDestroy();
    }
}
以上,就能實現靜默安裝和卸載,其實這邊使用的cmd是還可以實現更多的功能比如,adb shell中的am、wm指令


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章