3

I'm using reflection to call a method that is outside of the target API level of my Android application:

try {
    Method m = Class.forName("android.content.Context")
            .getDeclaredMethod("getExternalCacheDir");
    Object result = m.invoke(this);
    if (result instanceof File) {
        Log.v("MyApp", "external cache: "
                + ((File) result).getAbsolutePath());
        cacheDirectory = (File) result;
    } else {
        Log.v("MyApp", "non-file cache: " + result);
    }
} catch (Exception e) {
    // ...
}

I can optimize this without any problems through Proguard, but it warns me:

Note: com.example.MyApp accesses a declared method 'getExternalCacheDir()' dynamically
      Maybe this is library method 'android.content.Context { java.io.File getExternalCacheDir(); }'
      Maybe this is library method 'android.content.ContextWrapper { java.io.File getExternalCacheDir(); }'
      Maybe this is library method 'android.test.mock.MockContext { java.io.File getExternalCacheDir(); }'
Note: there were 1 accesses to class members by means of introspection.
      You should consider explicitly keeping the mentioned class members
      (using '-keep' or '-keepclassmembers').

Is this an actual problem, or is Proguard just informing me of a potential problem?

Paul Lammertsma
  • 37,593
  • 16
  • 136
  • 187
  • 1
    it's no problem for you. It warns that you should not proguard the Android framework since renaming framework methods would break your reflection. – zapl Apr 18 '12 at 15:44
  • True, and I'm aware of this danger. It would be better practice to raise the API target level and surround the function call with a `Build.VERSION.SDK_INT` check. Unfortunately the project library is used in legacy applications and is shrouded by something of a "hands-off" policy. – Paul Lammertsma Apr 18 '12 at 16:41
  • Hey, turns out the library was already set at SDK target 8! All I needed to do was wrap that check around it and replace the reflection with the function call! – Paul Lammertsma Apr 18 '12 at 16:45

2 Answers2

5

This is similar to the answer Paul Lammertsma posted. Also take a look at the author of ProGuard Eric Lafortune's answer at: How to suppress 'Maybe this is program method' warnings from ProGuard

You can avoid it by explicitly mentioning the method in the configuration:

-keep class com.foo.OtherClass { com.foo.OtherClass getInstance(); }

Alternatively, you can suppress notes on a class:

-dontnote com.foo.MyClass

Community
  • 1
  • 1
4

The problem resided in a library project that I was using, and the proguard.cfg from that project wasn't being inspected by Proguard.

By adding the following lines to my own projects proguard.cfg, I was able to make the notice disappear:

-keep class android.content.Context {
    public java.io.File getExternalCacheDir();
}
Paul Lammertsma
  • 37,593
  • 16
  • 136
  • 187