6

I´m developing a Cache-Cleaner application, and when I invoke a hidden method in PackageManager I get a SecurityException, though I have given my app the uses-permission "DELETE_CACHE_FILES"

The Uses-Permissions:

uses-permission android:name="android.permission.DELETE_CACHE_FILES"
uses-permission android:name="android.permission.CLEAR_APP_CACHE"
uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
uses-permission android:name="android.permission.CLEAR_APP_USER_DATA"
uses-permission android:name="android.permission.GET_PACKAGE_SIZE"

The reflected method:

Method method = getPackageManager().getClass().getMethod("deleteApplicationCacheFiles", String.class, IPackageDataObserver.class);

The Error:

java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at <MY_PACKAGE_NAME>.MainActivity$1.onClick(MainActivity.java:70)
at android.view.View.performClick(View.java:2485)
at android.view.View$PerformClick.run(View.java:9080)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:3683)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.SecurityException: Neither user 10037 nor current process has   android.permission.DELETE_CACHE_FILES.
at android.os.Parcel.readException(Parcel.java:1322)
at android.os.Parcel.readException(Parcel.java:1276)
at android.content.pm.IPackageManager$Stub$Proxy.deleteApplicationCacheFiles(IPackageManager.java:2346)
at android.app.ContextImpl$ApplicationPackageManager.deleteApplicationCacheFiles(ContextImpl.java:2562)
... 14 more

Line 70:

 method.invoke(getPackageManager(), app.packageName, dataObserver);

It says that I don´t have the permission, but I have decleared it in my manifest...

EDIT: I found out this;

W/PackageManager(62): Not granting permission android.permission.DELETE_CACHE_FILES to package <MY_PACKAGE_NAME>.cachecleaner (protectionLevel=3 flags=0x8be46)

EDIT2: Declaration of deleteApplicationCacheFiles(got it via method.toGenericString()):

public void android.app.ContextImpl$ApplicationPackageManager.deleteApplicationCacheFiles(java.lang.String, android.content.pm.IPackageDataObserver)
Vishal Pawar
  • 4,324
  • 4
  • 28
  • 54
MAA
  • 93
  • 3
  • 13
  • Got any solution to this? I'm curious – Kiran Parmar Apr 04 '14 at 10:07
  • @Mylleranton have u found any solution ? – Erum Nov 28 '14 at 04:24
  • @ErumHannan I remember finding a solution, but that was a couple of years ago. I also remember writing some half done application (looks terrible) but the cache cleaning part at least worked and was implemented. Since I don't remember how I fixed the problem, I'm attaching the entire project: https://www.dropbox.com/s/fjz221fbojm06uj/Utilities2.zip?dl=0 Feel free to use the code however you wish. – MAA Nov 28 '14 at 17:54
  • @KiranParmar Take a look at my comment above! – MAA Nov 28 '14 at 17:55
  • @Mylleranton can u pls help me how u delete cache ??? right now your project is not working there are some errors in code that listview is updating from background thread ??? pls can u help me – Erum Nov 29 '14 at 06:35
  • 1
    @ErumHannan The basis in my code for the cache deleting is the file 'Fragment_1.java' which when enabled (selected in a dropdown) immediately calculates the size of all the applications cache via 'CalculateCache()'. The cache cleaning itself is initiated from a button click ('onClick' method in 'Fragment_1'). There the method 'freeStorageAndNotify(Long, IPackageDataObserver)' is implemented and then invoked. As arguments when invoking I leave 'Long.MAX_VALUE' and an object of my class 'CacheObserver'. The observer basically gets a system call when an app's cache has been cleaned, and voila. – MAA Nov 29 '14 at 07:15
  • right now i m calling method clearCache() its getting called that has all methods but my observer is not getting called i have given permission in manifest as well but my oberserver is failed to listen @Mylleranton can u pls help me – Erum Nov 29 '14 at 07:30
  • @ErumHannan Have you successfully called the reflected method 'freeStorageAndNotify'? Your observer needs to be of the type (i.e extend) 'android.content.pm.IPackageDataObserver.Stub' and override 'onRemoveCompleted(String packageName, boolean succeeded)' in order to work. But firstly: Have you got the reflected method right? Secondly: How does your invoke call look like? Thirdly: How does your Observer look like? – MAA Nov 29 '14 at 07:39
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/65864/discussion-between-erum-hannan-and-mylleranton). – Erum Nov 29 '14 at 07:49

4 Answers4

6

DELETE_CACHE_FILES is a signature|system permission, meaning that it can only be held by apps that are signed with the firmware's signing key or are installed on the system partition (e.g., by a rooted device user). Ordinary SDK applications cannot hold this permission.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • How would I go about cleaning another applications cache then? If these permissions stops me from accessing the cache directory, then what would I do? – MAA Dec 26 '12 at 13:51
  • 1
    @Mylleranton: I know of no way for you to clear the cache of an individual application. – CommonsWare Dec 26 '12 at 13:54
  • If I add my application as a device admin, would it work then? Or, would I be granted that permission then? – MAA Dec 26 '12 at 14:05
  • @Mylleranton: Being a device admin does not affect what permissions you can hold. All it does is allow you to use various methods on `DevicePolicyManager`, none of which have anything to do with application caches (IIRC). – CommonsWare Dec 26 '12 at 14:06
  • 1
    Hello CommonsWare, thanks for the answer :) But there is an app in playstore All-in-one Toolbox "https://play.google.com/store/apps/details?id=imoblife.toolbox.full&hl=en", they are seeking accessibility permission, with that they are able to clean cache of other apps. – Chethan Shetty Jun 05 '16 at 04:49
3
try to use this i tried this code and it worked for me...

private static final long CACHE_APP = Long.MAX_VALUE;
private CachePackageDataObserver mClearCacheObserver; 
void clearCache() {
    if (mClearCacheObserver == null) {
        mClearCacheObserver = new CachePackageDataObserver();
    }

    PackageManager mPM = getPackageManager();

    @SuppressWarnings("rawtypes")
    final Class[] classes = { Long.TYPE, IPackageDataObserver.class };

    Long localLong = Long.valueOf(CACHE_APP);

    try {
        Method localMethod = mPM.getClass().getMethod(
                "freeStorageAndNotify", classes);

        /*
         * Method localMethod=mPM.getClass()
         * .getDeclaredMethod("deleteApplicationCacheFiles", String.class,
         * IPackageDataObserver.class );
         */
        /*
         * Start of inner try-catch block
         */
        try {
            localMethod.invoke(mPM, localLong, mClearCacheObserver);
            // localMethod.invoke(mPM, packageName, mClearCacheObserver);
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        /*
         * End of inner try-catch block
         */
    } catch (NoSuchMethodException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
}

private class CachePackageDataObserver extends IPackageDataObserver.Stub {
    public void onRemoveCompleted(String packageName, boolean succeeded) {
        runOnUiThread(new Runnable() {
            public void run() {

                Toast.makeText(MainActivity.this, "cache memory cleared",
                        5000).show();
            }
        });

        Log.d("cachedel", "cache deleted");
    }// End of onRemoveCompleted() method
}
neeraj kirola
  • 258
  • 2
  • 13
1

Do you invoke this:

method.setAccessible(true);
Roman Makhlin
  • 973
  • 1
  • 11
  • 27
-1

Try this function freeStorageAndNotify with premission

android.permission.CLEAR_APP_CACHE

.