1

I am new in Android programming. I want to invoke a method in the class BatteryService by reflection. However, the following code fails above Android 5.0, including the newest Android 6.0.1, though it succeeds in Android 4.3. I have googled for days. But I cannot find any useful answers.

try{
        Class myclass = Class.forName("com.android.server.BatteryService");
   } catch (ClassNotFoundException e) {
        e.printStackTrace();
        Log.d("xx", "ClassNotFound!");
   }

I have checked the source of Android 4.3, 5.0 and 6.0.1, and I am sure that the class BatteryService is in com.android.server. BTW, the modifier of BatteryService is public.

When running the above code, Android 5.0+ report an exception that the Class cannot be found. But the code works in Android 4.3. I wonder there are any new features introduced in Android 5.0 to preventing reflection?

Anyone knows the reason. Thanks a million!

Ting Chen
  • 79
  • 2

3 Answers3

0

Probably classloader doesn't know that class. App classloader and system classloader are not same.


EDITED

When starting systemserver, class path has set. So, probably system app doesn't have this classloader.

https://android.googlesource.com/platform/frameworks/base.git/+/master/core/java/com/android/internal/os/ZygoteInit.java#461

    /**
     * Finish remaining work for the newly forked system server process.
     */
    private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller {
....
            ClassLoader cl = null;
            if (systemServerClasspath != null) {
                cl = new PathClassLoader(systemServerClasspath, ClassLoader.getSystemClassLoader());
                Thread.currentThread().setContextClassLoader(cl);
            }
            /*
             * Pass the remaining arguments to SystemServer.
             */
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
takahirom
  • 1,934
  • 2
  • 12
  • 21
  • Do you mean I should use system class loader to load the class. Then I use the following code ClassLoader classloader = ClassLoader.getSystemClassLoader(); classloader.loadClass("com.android.server.BatteryService"); It is also failed due to ClassNotFound exeception. Perhaps I have to try install the app in /system/app as cgarrido said. – Ting Chen Jan 05 '16 at 03:31
0

As answered before, the classloader can't found the class. This is because the scope of the package is invisible if you don't have system's permissions (your apk should be installed in /system/app).

I recommend you to read this doc

crgarridos
  • 8,758
  • 3
  • 49
  • 61
0

You should avoid reflection and use the service class BatteryManager.

http://developer.android.com/reference/android/os/BatteryManager.html

intrepidis
  • 2,870
  • 1
  • 34
  • 36