uninstall app silently with system privileges

20.9k views Asked by At

My app have system privileges. It will be inside firmware, now it's located at /system/app

I was able to install apps silently with this post

install / uninstall APKs programmatically (PackageManager vs Intents)

example app that works

http://paulononaka.wordpress.com/2011/07/02/how-to-install-a-application-in-background-on-android/

But I still can't uninstall apps the same way. I tried to use reflection like as in the installation example.

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});
    }

I have added uninstallPackage method and edited ApplicationManager method. Still cant get this working.

When I run it I get method not found (on the invoke "deletePackage" line).

Here is not working project with my changes: https://dl.dropbox.com/u/1928109/InstallInBackgroundSample.zip

Here is an description of function: http://www.androidjavadoc.com/1.0_r1_src/android/content/pm/PackageManager.html#deletePackage(java.lang.String, android.content.pm.IPackageDeleteObserver, int)

Parameters are ok. Seems like I should specify DeletePackageObserver class instead of InstallPackageObserver. But I don't know how to do that (I don't have such class).

Thanks

4

There are 4 answers

14
POMATu On BEST ANSWER

Here is how I did it:

ApplicationManager.java (changed part):

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 (in 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;
}

Also dont forget to add permission to manifest:

<uses-permission android:name="android.permission.DELETE_PACKAGES"/>

Working sample project (apk need to be placed in "/system/app" path on device): http://www.mediafire.com/file/no4buw54ed6vuzo/DeleteInBackgroundSample.zip

0
hackbod On

If you are having your app built into the system image, and you are using internal APIs, you might as well stop pretending like you are a third party app and linking against the SDK. Build against the full platform .jar and use those APIs directly. You want to do that anyway, because these are private APIs, and so they can and do change. You want to build against what is actually declaring them, so if they do change, you will catch this during your builds.

7
Nikolay Elenkov On

This is how the method is defined:

   public abstract void deletePackage(
             String packageName, IPackageDeleteObserver observer, int flags);

To call it using reflection, you would need something like:

Class<?>[] uninstalltypes = new Class[] {String.class, 
         IPackageDeleteObserver.class, int.class};
uninstallmethod = pm.getClass().getMethod("deletePackage", uninstalltypes);

Note the type of the observer.

0
firebear On

in android 2.3.x, the interface IPackageDeleteObserver is different in method packageDeleted.