13

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

Andrey Belykh
  • 2,578
  • 4
  • 32
  • 46
POMATu
  • 3,422
  • 7
  • 30
  • 42

4 Answers4

18

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

POMATu
  • 3,422
  • 7
  • 30
  • 42
  • @pyus13 : i think that it will work just for rooted devices , otherwise, take a look at this example : it's working on both (rooted and non rooted devices ) : http://impressive-artworx.de/2011/uninstall-an-app-programmatically/ – Houcine Mar 08 '13 at 15:43
  • @Houcine thanks but it will ask for a user confirmation to delete the app but I am looking for something which will directly uninstall the application, all applications are developed by mine only generated with same certificate so can I uninstall my own developed application from my another developed application without any user promt ? – Piyush Agarwal Mar 09 '13 at 12:40
  • @POMATu , I think normally your code works. But how about the APP with device admin activated? Seems it will check device admin inside the method "deletePackage". Thanks. – posaidong Jul 29 '13 at 09:20
  • @POMATu I am trying to develop app with system Privileges for Rooted Device. It can prevent new application install in that device. Could you suggest me any link for tutorial? – Amy Jul 25 '15 at 10:12
  • @Amy what do you mean by "prevent new app install"? What are you trying to achieve? – POMATu Jul 26 '15 at 14:39
  • @posaidong I think it won't work with device admin activated. This permission is granted to only system apps that are located in /system/app – POMATu Jul 26 '15 at 14:40
  • @POMATu I am trying to develop something like kiosk app. Device allows only one app to run on launch remaining app installation should be locked. – Amy Jul 27 '15 at 10:14
  • @POMATu Hi, I develop a custom launcher using Android Studio 22, and I follow your codes, then I added the permission DELETE_PACKAGES in my AndroidManifest (error appeared but I ignore), so I ran my app using Geny Motion emulator. But I still received error that my app doesn't have a permission ... any idea? – Bromo Programmer Jan 16 '17 at 09:07
  • @BromoProgrammer have you put your app in /system/app directory? This permission only works for system apps. – POMATu Jan 18 '17 at 20:19
  • @POMATu, is this as copying the APK into the /system/app directory then execute installation from there? or when I execute install, it is installed there? (sorry I still confused)... – Bromo Programmer Jan 19 '17 at 00:46
  • @BromoProgrammer when you put apk to that folder it's automatically installed in 1 minute. If not - you can also reboot the device, then it's definately should appear as installed. – POMATu Jan 20 '17 at 16:59
  • @POMATu, hi .. I still got permission error ... I think I must create a custom ROM then .... thanks anyway – Bromo Programmer Jan 23 '17 at 06:59
  • @POMATu Installation Works but I am unable to Uninstall Packages? – Dhruv Kaushal Mar 28 '18 at 12:33
  • THIS SOLUTION IS WORKING OCT-09-2020 TESTED ON ANDROID 23, only issue is its not explained properly. – Irfan Anwar Oct 09 '20 at 13:53
7

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.

Nikolay Elenkov
  • 52,576
  • 10
  • 84
  • 84
  • But I do not have packageDeleteObserver class in sample program. The coder from wordpress blog provided only packageInstallObserver, and it differs from packageInstallObserver from android system. – POMATu Jun 08 '12 at 02:26
  • Well, use your imagination :) Add a stub `IPackageDeleteObserver` class to your project, just as how the blog describes they did it for `IPackageInstallObserver`. – Nikolay Elenkov Jun 08 '12 at 02:30
  • look. While this line is okay `observer = new PackageInstallObserver();`, I have problems using this line `observerdelete = new PackageDeleteObserver();`. It says PackageDeleteObserver can't be resolved to a type, but it exists in my project. Here is the project with your changes that do not compile https://dl.dropbox.com/u/1928109/InstallInBackgroundSample2.zip – POMATu Jun 08 '12 at 02:47
  • 1
    Surely you don't expect me to do you work for you? Check the errors and fix them. Compare with the original project/class, find the differences. Is the class in the right package? Have you imported it? Etc., etc. – Nikolay Elenkov Jun 08 '12 at 02:54
  • It's finally worked. Thanks. I will create detailed answer soon. – POMATu Jun 08 '12 at 03:14
  • @NikolayElenkov will this technique be useful for unrooted devices or you need to have root access to call deletePackage() function using reflection. – Piyush Agarwal Dec 23 '12 at 10:18
  • You don't need root access to call it. You do need root access to gain the permissions required to execute it. If your app is installed in `/system/app` or signed with the platform certificate, this will also work (that is how the Google Play Store client works). This is mostly useful if you are developing your own firmware (custom ROM, etc.), of course. – Nikolay Elenkov Dec 23 '12 at 13:40
4

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.

hackbod
  • 90,665
  • 16
  • 140
  • 154
1

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

firebear
  • 774
  • 1
  • 8
  • 19