该主题在很大程度上已经在SO和其他地方讨论过,但是由于某些我失踪的原因我无法申请.
这个范围显然很难实现,因为如果成功,Android将会是严重的安全漏洞.但是,我需要实施一个特殊的项目,而不是为了消费市场.
有两种方法:
>通过调整PackageManager安装程序(实际上只是删除用户接受对话框),从源代码(例如AOSP或Cyanogen mod)生成自定义ROM.
>以编程方式通过创建超级用户进程并执行“adb shell pm install”进行编程.我以前在/ system / xbin中安装了’su’,我在运行时测试了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文件参数; on’case R.id.btnInstall’命令不执行,退出是“失败”,退出值为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; } } }
>在/ src中创建com.example.instuninsthelper包.我已经添加了ApplicationManager.java和OnInstalledPackage.java文件
>在ApplicationManager类中插入以下代码:
private OnDeletedPackage onDeletedPackage; class PackageDeleteObserver extends IPackageDeleteObserver.Stub { public void packageDeleted(boolean succeeded) throws RemoteException { if (onDeletedPackage != null) { onDeletedPackage.packageDeleted(succeeded); } } }
>创建,在同一个com.example.instuninsthelper下使用以下代码打包OnDeletedPackage.java文件:
package com.example.instuninsthelper; public interface OnDeletedPackage { public void packageDeleted(boolean succeeded); }
>在android.content.pm包中(命名空间应该不要更改)我修改了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; }
>在Eclipse中构建应用程序并将其部署到仿真器
>在模拟器中:主页按钮>设置>应用> …卸载应用程序(因为它没有安装在/ system / app中,我们只需要生成apk文件)
>执行以下操作来根除模拟器(以便我们可以在/ system / app中编写;我使用的其他解决方案是生成一个包含在/ system / app中的此应用程序的自定义ROM):
>从这里下载su文件http://forum.xda-developers.com/showthread.php?t=682828http://forum.xda-developers.com/showthread.php?t=682828.将其重命名为su.zip
>然后从控制台:
* adb shell mount -o rw,remount -t yaffs2 / dev / block / mtdblock03 / system
* adb push su.zip / system / xbin / su
* adb shell chmod 06755 / system
* adb shell chmod 06755 / system / xbin / su
>从控制台,转到项目的/ bin目录,然后输入:* adb push .apk / system / app>最后,总是从控制台输入:* adb shell am start -n com.example.silentinstuninst / com.example.silentinstuninst.MainActivity>享受!