Удалить приложение в автоматическом режиме с системными привилегиями
Мое приложение имеет системные привилегии. Он будет внутри прошивки, теперь он находится в /system/app
Я смог установить приложения в этом сообщении без уведомления
установить / удалить APK программно (PackageManager vs Intents)
пример приложения, которое работает
http://paulononaka.wordpress.com/2011/07/02/how-to-install-a-application-in-background-on-android/
Но я все еще не могу удалить приложения таким же образом. Я попытался использовать отражение, как в примере установки.
public ApplicationManager(Context context) throws SecurityException, NoSuchMethodException {
observer = new PackageInstallObserver();
pm = context.getPackageManager();
Class<?>[] types = new Class[] {Uri.class, IPackageInstallObserver.class, int.class, String.class};
Class<?>[] uninstalltypes = new Class[] {String.class, IPackageInstallObserver.class, int.class};
method = pm.getClass().getMethod("installPackage", types);
uninstallmethod = pm.getClass().getMethod("deletePackage", uninstalltypes);
}
public void uninstallPackage(String packagename) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
uninstallmethod.invoke(pm, new Object[] {packagename, observer, 0});
}
public void installPackage(Uri apkFile) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
method.invoke(pm, new Object[] {apkFile, observer, INSTALL_REPLACE_EXISTING, null});
}
Я добавил метод uninstallPackage и изменил метод ApplicationManager. Все еще не могу заставить это работать.
Когда я запускаю его, я получаю метод not found (в строке вызова "deletePackage").
Здесь не работает проект с моими изменениями: https://dl.dropbox.com/u/1928109/InstallInBackgroundSample.zip
Вот описание функции: http://www.androidjavadoc.com/1.0_r1_src/android/content/pm/PackageManager.html, android.content.pm.IPackageDeleteObserver, int)
Параметры в порядке. Похоже, я должен указать класс DeletePackageObserver вместо InstallPackageObserver. Но я не знаю, как это сделать (у меня нет такого класса).
Спасибо
4 ответа
Вот как я это сделал:
ApplicationManager.java (измененная часть):
private PackageInstallObserver observer;
private PackageDeleteObserver observerdelete;
private PackageManager pm;
private Method method;
private Method uninstallmethod;
class PackageDeleteObserver extends IPackageDeleteObserver.Stub {
public void packageDeleted(String packageName, int returnCode) throws RemoteException {
/*if (onInstalledPackaged != null) {
onInstalledPackaged.packageInstalled(packageName, returnCode);
}*/
}
}
public ApplicationManager(Context context) throws SecurityException, NoSuchMethodException {
observer = new PackageInstallObserver();
observerdelete = new PackageDeleteObserver();
pm = context.getPackageManager();
Class<?>[] types = new Class[] {Uri.class, IPackageInstallObserver.class, int.class, String.class};
Class<?>[] uninstalltypes = new Class[] {String.class, IPackageDeleteObserver.class, int.class};
method = pm.getClass().getMethod("installPackage", types);
uninstallmethod = pm.getClass().getMethod("deletePackage", uninstalltypes);
}
public void uninstallPackage(String packagename) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
uninstallmethod.invoke(pm, new Object[] {packagename, observerdelete, 0});
}
PackageDeleteObserver.java (в android.content.pm):
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(java.lang.String packageName, int returnCode)
throws android.os.RemoteException;
}
Также не забудьте добавить разрешение на манифест:
<uses-permission android:name="android.permission.DELETE_PACKAGES"/>
Рабочий пример проекта (файл apk необходимо поместить в путь "/system/app" на устройстве): http://www.mediafire.com/file/no4buw54ed6vuzo/DeleteInBackgroundSample.zip
Вот как определяется метод:
public abstract void deletePackage(
String packageName, IPackageDeleteObserver observer, int flags);
Чтобы вызвать его с помощью отражения, вам нужно что-то вроде:
Class<?>[] uninstalltypes = new Class[] {String.class,
IPackageDeleteObserver.class, int.class};
uninstallmethod = pm.getClass().getMethod("deletePackage", uninstalltypes);
Обратите внимание на тип наблюдателя.
Если ваше приложение встроено в образ системы и вы используете внутренние API-интерфейсы, вы можете перестать притворяться, будто вы стороннее приложение, и ссылаться на SDK. Сборка с полной платформой.jar и использование этих API напрямую. В любом случае вы хотите сделать это, потому что это частные API, и поэтому они могут и действительно изменятся. Вы хотите строить против того, что фактически объявляет их, поэтому, если они действительно изменятся, вы поймете это во время ваших сборок.
В Android 2.3.x интерфейс IPackageDeleteObserver отличается в методе packageDeleted.