8

Precondition and build config: I am trying to build my app with AndroidStudio 2.4 review 5 by setting below build config paramters for Android O perview device, compileSdkVersion 'android-O' buildToolsVersion '25.0.0' compileOptions.encoding = 'ISO-8859-1' minSdkVersion 16 targetSdkVersion 'O' // Enabling multidex support. multiDexEnabled true

Issue Description: My app uses these below deprecated methods of ConnectivityManager class for devices with older version of android. -ConnectivityManager.startUsingNetworkFeature() - ConnectivityManager.stopUsingNetworkFeature() - ConnectivityManager.requestRouteToHost()

When I try to build my app which has these above api, it is giving compile time error as follows,

Error:(626, 48) error: cannot find symbol method startUsingNetworkFeature(int,String) Error:(7393, 27) error: cannot find symbol method stopUsingNetworkFeature(int,String) Error:(69, 36) error: cannot find symbol method requestRouteToHost(int,int)

Ideally these api should not give compile time error for backward compatibity purpose. Please let me know how to resolve these compile time errors.

I can't remove these methods from code as they are required for devices with older android version(less than Android L version)

Mallik
  • 129
  • 1
  • 7

5 Answers5

3

Make an new android library module in your project. Make sure this library has compileSdkVersion 25. Then put the following class inside the library:

@SuppressWarnings("Deprecation")
public class NetworkFeaturesCompat {
    public static NetworkFeaturesCompat from(final ConnectivityManager cm) {
        return new NetworkFeaturesCompat(cm);
    }

    private final ConnectivityManager mConnectivityManager;

    private NetworkFeaturesCompat(final ConnectivityManager cm) {
        mConnectivityManager = cm;
    }

    public int startUsingNetworkFeature(final int networkType, final String feature) {
        return mConnectivityManager.startUsingNetworkFeature(networkType, feature);
    }

    public int stopUsingNetworkFeature(final int networkType, final String feature) {
        return mConnectivityManager.stopUsingNetworkFeature(networkType, feature);
    }

    public boolean requestRouteToHost(final int networkType, final int hostAddress) {
        return mConnectivityManager.requestRouteToHost(networkType, hostAddress);
    }
}

Now make your main module depend on this library by altering its build.gradle file:

dependencies {
    compile project(":your-new-library-module-name")
}

Build your project.

Now you can use this helper class from your main project.

You may need to add this to your proguard rules (I haven't actually tested this bit):

-dontwarn android.net.ConnectivityManager

Please note that this approach will still throw UnsupportedOperationException on Android 6+.

Why this works?

The original methods are still present in the SDK, they're just hidden from public API in SDK 26. This is why it doesn't crash at run time.

The library module is compiled against SDK 25 where the methods are still part of public API. This is why it doesn't crash at compile time.

Since the whole project is compiled against SDK 26 proguard may complain about missing methods. In that case just ignore the complaint.

Eugen Pechanec
  • 37,669
  • 7
  • 103
  • 124
  • https://developer.android.com/sdk/api_diff/26/changes/android.net.ConnectivityManager.html API's are removed not deprecated..isn't? – NitZRobotKoder Oct 24 '17 at 07:34
  • @NitZRobotKoder The methods are just hidden so you can't use them directly if you compile against SDK 26. The actual methods are still there. And the library module will compile just fine because it's compiled against SDK 25. – Eugen Pechanec Oct 24 '17 at 07:36
  • Ok..have you tried above lib format with(Compile 25) and it works? Im Checking reflection way.. – NitZRobotKoder Oct 24 '17 at 07:48
  • @NitZRobotKoder Yeah, it worked. But I suspect reflection may be faster when you do the lookup just once. – Eugen Pechanec Oct 24 '17 at 07:52
3

Because I cannot add comments to Antilope's answer, I will correct it here.

It should be method.invoke(connectivityManager, ConnectivityManager.TYPE_MOBILE, "enableHIPRI");

So in general the code looks like:

try{
    java.lang.reflect.Method method = connectivityManager.getClass().getMethod("startUsingNetworkFeature",
    int.class, String.class); 
    resultInt = (int) method.invoke(connectivityManager, ConnectivityManager.TYPE_MOBILE, 
"enableHIPRI");
} catch (Exception e) { 
    //Do something 
}

and

try{
    java.lang.reflect.Method method = connectivityManager.getClass().getMethod("requestRouteToHost", int.class, int.class);
    resultBool = (boolean) method.invoke(connectivityManager, ConnectivityManager.TYPE_MOBILE_HIPRI, hostAddress);
} catch (Exception e) { 
    //Do something 
}

The above works on targetSDK 27

Janusz Drobiński
  • 101
  • 1
  • 1
  • 4
1

As suggested on thes bug report thread (https://issuetracker.google.com/issues/64992660), calling though reflection works even while targeting API 27. Tested on different devices, even on a Galaxy Note8 withe Oreo (8.0.0).

What i previously called:

resultInt = connectivityManager.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, "enableHIPRI");

now can be called as:

try{
    java.lang.reflect.Method method = connectivityManager.getClass().getMethod("startUsingNetworkFeature",
    int.class, String.class); resultInt = (int) method.invoke(ConnectivityManager.TYPE_MOBILE, "enableHIPRI");
} catch (Exception e) { 
    //Do something 
}

And also works for:

resultBool = connectivityManager.requestRouteToHost(ConnectivityManager.TYPE_MOBILE_HIPRI, hostAddress);

now can be called as:

try{
    java.lang.reflect.Method method = connectivityManager.getClass().getMethod("requestRouteToHost", int.class, int.class);
    resultBool = (boolean) method.invoke(ConnectivityManager.TYPE_MOBILE_HIPRI, hostAddress);
} catch (Exception e) { 
    //Do something 
}
Antilope
  • 340
  • 2
  • 10
0

For Android versions below L, a reflection way of calling the startUsingNetworkFeature, stopUsingNetworkFeature, requestRouteToHost will help.

Google should come up with COMPATIBILITY support.

Abandoned Cart
  • 4,512
  • 1
  • 34
  • 41
NitZRobotKoder
  • 1,046
  • 8
  • 44
  • 74
0

Make sure your library module has compileSdkVersion 25.

Makvin
  • 3,475
  • 27
  • 26