从Android中壳命令安装/反安装(Install / Unistall from shell c

2019-07-19 20:57发布

我想实现一个静默安装程序,从-的apk文件在Android和unistaller包。 该主题已在很大程度上被SO和其他地方讨论的,但我不能因为某些原因我就是缺少任何申请。 范围显然是很难实现的,因为,如果成功,这将是Android的一个严重的安全漏洞。 但是,我需要实现在一个特殊的项目,而不是为消费市场。 有两种方法:

  1. 以产生从源代码的自定义ROM(AOSP或氰MOD,例如),通过调整PackageManager安装程序(实际上只是以除去用户接受对话框)。
  2. 通过创建一个过程,超级用户和执行的“亚行外壳时安装”做编程。 我以前安装的“素”在/系统/ XBIN和在运行时我测试RootTools.rootIsAvailable()。

对于第一种情况,我挖成Froyo的源代码,但陷入了@hide标记方法是死路一条。 对于第二个我首先尝试从终端的命令

adb shell pm install /mnt/sdcard/HelloAndroid.apk

adb shell pm uninstall com.example.helloandroid

都工作正常。 然后,我用下面的代码,在一个根仿真器(2.2 - Froyo的)所测试的发展:

@Override
    public void onClick(View v) {
        switch (v.getId())
           {
              case R.id.btnInstall:
                  try {  
                      install = Runtime.getRuntime().exec("su\n");   
                      DataOutputStream os = new DataOutputStream(install.getOutputStream());
                      os.writeBytes("pm install /mnt/sdcard/HelloAndroid.apk\n"); 
                      os.writeBytes("exit\n"); 
                      os.flush();
                      install.waitFor();

                              if (install.exitValue() == 0) {  
                                  Toast.makeText(MainActivity.this, "Success!", Toast.LENGTH_LONG).show();
                              }  
                              else {  
                                  Toast.makeText(MainActivity.this, "Failure. Exit code: "+String.valueOf(install.exitValue()), Toast.LENGTH_LONG).show();
                              }
                  }
                  catch (InterruptedException e) {  
                      logError(e);
                  }
                  catch (IOException e) {  
                  logError(e);
                  } 
                  break;

              case R.id.btnUninstall:
                  try {
                      install = Runtime.getRuntime().exec("su\n"); 
                      install=Runtime.getRuntime().exec("pm uninstall "+txtPackageName.getText().toString()+"\n");

                } catch (Exception e) {
                    logError(e);
                }
                  break;
           }

    }

为了避免输入错误等装饰我硬编码为安装命令的apk文件参数; 上“的情况下R.id.btnInstall”不执行命令和出射的是“失败”,退出值1,这意味着“之类无法找到”; 不知道这是什么意思......我感谢您的帮助!

编辑:我有干净的解决方案,我只要我有足够的时间和正确的形式发布的代码从AZ的答案!

Answer 1:

正如我答应这里是解决这个问题,没有做任何强迫到不必安装在/ system / app目录整个应用程序的其他系统。 我跟随,然后做了一些固定的优秀文章在这里: http://paulononaka.wordpress.com/2011/07/02/how-to-install-a-application-in-background-on-android/ 。 我已经下载的文章,然后在引用的zip文件,(我试图保持相同的类名称如果可能):

  1. 创建一个新的项目,并为切入点主要活动

package com.example.silentinstuninst;

import java.io.File;
import java.lang.reflect.InvocationTargetException;

import com.example.instuninsthelper.ApplicationManager;
import com.example.instuninsthelper.OnDeletedPackage;
import com.example.instuninsthelper.OnInstalledPackage;

import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener {

    Process install;
    Button btnInstall, btnUninstall;
    EditText txtApkFileName, txtPackageName; 

    public static final String TAG = "SilentInstall/Uninstall";

    private static ApplicationManager am;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initializeValues();

    }

    private void initializeValues() {

        btnInstall = (Button) findViewById(R.id.btnInstall);
        btnUninstall = (Button) findViewById(R.id.btnUninstall);
        txtApkFileName = (EditText) findViewById(R.id.txtApkFilePath);
        txtPackageName = (EditText) findViewById(R.id.txtPackageName);

        btnInstall.setOnClickListener(this);
        btnUninstall.setOnClickListener(this);

        try {
            am = new ApplicationManager(this);
            am.setOnInstalledPackage(new OnInstalledPackage() {

                public void packageInstalled(String packageName, int returnCode) {
                    if (returnCode == ApplicationManager.INSTALL_SUCCEEDED) {
                        Log.d(TAG, "Install succeeded");
                    } else {
                        Log.d(TAG, "Install failed: " + returnCode);
                    }
                }
            });

            am.setOnDeletedPackage(new OnDeletedPackage() {
                public void packageDeleted(boolean succeeded) {
                    Log.d(TAG, "Uninstall succeeded");  
                }
            });

        } catch (Exception e) {
            logError(e);
        }
    }

    private void logError(Exception e) {
        e.printStackTrace();
        Toast.makeText(this, R.string.error+e.getMessage(), Toast.LENGTH_LONG).show();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId())
           {
              case R.id.btnInstall:
                  // InstallUninstall.Install(txtApkFileName.getText().toString());
            try {
                am.installPackage(Environment.getExternalStorageDirectory() +
                        File.separator + txtApkFileName.getText().toString());
            } catch (IllegalArgumentException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            } catch (IllegalAccessException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            } catch (InvocationTargetException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            } // install package
                  break;

              case R.id.btnUninstall:
                  // InstallUninstall.Uninstall(txtPackageName.getText().toString());
            try {
                am.uninstallPackage(txtPackageName.getText().toString());
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                logError(e);
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                logError(e);
            } catch (InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                logError(e);
            }
                  break;
           }    
    }
}
  1. 创建/ src中的包com.example.instuninsthelper。 我已经加入那里的ApplicationManager.java和OnInstalledPackage.java文件
  2. 插入ApplicationManager类内部以下代码:

private OnDeletedPackage onDeletedPackage;
class PackageDeleteObserver extends IPackageDeleteObserver.Stub { 

        public void packageDeleted(boolean succeeded) throws RemoteException {
            if (onDeletedPackage != null) {
                onDeletedPackage.packageDeleted(succeeded);
            }
        }

    }
  1. 创建的,相同的com.example.instuninsthelper包中的文件下OnDeletedPackage.java用下面的代码:

package com.example.instuninsthelper;
public interface OnDeletedPackage {
    public void packageDeleted(boolean succeeded);
}
  1. 在android.content.pm包(命名空间不应当被改变的)I修改IPackageDeleteObserver.java,这个结果:

package android.content.pm;

public interface IPackageDeleteObserver extends android.os.IInterface {

    public abstract static class Stub extends android.os.Binder implements android.content.pm.IPackageDeleteObserver {
        public Stub() {
            throw new RuntimeException("Stub!");
        }

        public static android.content.pm.IPackageDeleteObserver asInterface(android.os.IBinder obj) {
            throw new RuntimeException("Stub!");
        }

        public android.os.IBinder asBinder() {
            throw new RuntimeException("Stub!");
        }

        public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)
                throws android.os.RemoteException {
            throw new RuntimeException("Stub!");
        }
    }

    public abstract void packageDeleted(boolean succeeded)
            throws android.os.RemoteException;
}
  1. 在Eclipse构建应用程序并将其部署到模拟器
  2. 在模拟器:home键>设置>应用程序> ...卸载应用程序(因为它没有安装在/ system / app中,我们只需要apk文件的生成)
  3. 执行以下操作以根模拟器(使我们可以在写/系统/应用程序;其他解决方案,我所使用的,是生成自定义ROM与此应用程序包括到/系统/应用):
    • 从这里下载su文件http://forum.xda-developers.com/showthread.php?t=682828http://forum.xda-developers.com/showthread.php?t=682828 。 它重命名为su.zip
    • 然后从控制台:* ADB壳安装邻RW,重新装载-t YAFFS2的/ dev /块/ mtdblock03 /系统·ADB推su.zip /系统/ XBIN /苏* ADB壳CHMOD 06755 /系统·ADB壳CHMOD 06755 /系统/ XBIN /苏
  4. 从控制台,进入该项目的/ bin目录,然后输入:*亚洲开发银行推动的apk /系统/应用程序
  5. 最后,总是从控制台,输入:*亚行外壳上午开始-n com.example.silentinstuninst / com.example.silentinstuninst.MainActivity
  6. 请享用!


Answer 2:

不知道,但只是一个想法:

我认为你正在写在standarout,不执行命令,也没有通过其输入过程中所给予的额外数据。 我觉得应该是:

Runtime.getRuntime().exec("pm install /mnt/sdcard/HelloAndroid.apk\n"); 

希望这可以帮助。



Answer 3:

在安装/system/app目录是基本上相同,需要根。

假设你有根,退房RootTools 。 然后,你可以这样做:

if (RootTools.isAccessGiven()) {
    CommandCapture command = new CommandCapture(0, "pm install " + PATH_TO_APK);
    RootTools.getShell(true).add(command).waitForFinish();
}

需要注意的是waitForFinish()是一个阻塞调用!



Answer 4:

那么你也可以做这个直接用PackageManager(需要root权限):

  • 用平台的SDK,其公开有接口创建一个应用程序(创建或下载它,并配置Eclipse)
  • 在应用程序中直接调用隐藏的API函数允许静默安装/删除。
  • 将其复制到/系统/应用程序将设备用作系统的应用上安装APK(根需要)

看到这一点: http://forum.xda-developers.com/showthread.php?t=1711653



Answer 5:

。调用Runtime.getRuntime()EXEC( “PM安装/mnt/sdcard/HelloAndroid.apk\n”);

这对我的作品,虽然两个额外的细节都要做:

  1. 添加机器人:sharedUserId = “android.uid.system”在AndroidManifest.xml中。

  2. 签订利用系统密钥的APK。

    但这种方式似乎是没有办法告诉是否安装成功,所以后来我会尽量@姜的方法。



Answer 6:

对于所有谁仍然有问题:你需要一个植根设备和使用

Process result = Runtime.getRuntime().exec("pm install -r -d MyApp.apk /system/app")

如果您收到结果代码9(错误代码9),您将需要从设备中删除您的APK,并推回(推不INSTAL!)。

转至设备外壳和推APK

launcher=MyApp.apk
$adb shell su -c "mount -o remount,rw -t rfs /dev/stl5 /system"
$adb push $launcher /sdcard/$launcher
$adb shell su -c "chmod 644 /system/app/$launcher"

现在,您可以使用安装时没有得到一个错误。 希望这将帮助别人。



文章来源: Install / Unistall from shell command in Android