androidapn

How to use addOverrideApn() method in Android API level 28?


I'm trying to create a mobile application to manage APN(Access Point Name). In first I need to add an APN into the mobile application. I followed this documentation.

https://developer.android.com/reference/android/telephony/data/ApnSetting.Builder

I did as follows.

package com.example.myapplication;

import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.telephony.data.ApnSetting;
import android.util.Log;

import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;

import java.net.InetAddress;
import java.net.UnknownHostException;

public class MainActivity extends AppCompatActivity {
    private static String TAG = "MainActivity";

    @RequiresApi(api = Build.VERSION_CODES.P)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Create an MMS proxy address with a hostname. A network might not be
        // available, so supply a dummy (0.0.0.0) IPv4 address to avoid DNS lookup.
        String host = "mms.example.com";
        byte[] ipAddress = new byte[4];
        InetAddress mmsProxy;
        try {
            mmsProxy = InetAddress.getByAddress(host, ipAddress);
        } catch (UnknownHostException e) {
            e.printStackTrace();
            return;
        }
        ApnSetting apn=null;
        try{
           apn = new ApnSetting.Builder()
                .setApnTypeBitmask(ApnSetting.TYPE_DEFAULT | ApnSetting.TYPE_MMS)
                .setApnName("apn.example.com")
                .setEntryName("Example Carrier APN")
                .setMmsc(Uri.parse("http://mms.example.com:8002"))
                .setMmsProxyAddress(mmsProxy)
                .setMmsProxyPort(8799)
                .build();
        }catch (NoClassDefFoundError error){
            error.printStackTrace();
        }
        ComponentName componentName = new ComponentName(this, MainActivity.class);
        DevicePolicyManager devicePolicyManager = (DevicePolicyManager) getApplicationContext().getSystemService(Context.DEVICE_POLICY_SERVICE);
        devicePolicyManager.addOverrideApn(componentName,apn);
    }
}

But it gets the following error.

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.myapplication, PID: 24556
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.myapplication/com.example.myapplication.MainActivity}: java.lang.SecurityException: No active admin ComponentInfo{com.example.myapplication/com.example.myapplication.MainActivity}
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3160)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3303)
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1991)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:216)
    at android.app.ActivityThread.main(ActivityThread.java:7258)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:975)
    Caused by: java.lang.SecurityException: No active admin ComponentInfo{com.example.myapplication/com.example.myapplication.MainActivity}
    at android.os.Parcel.createException(Parcel.java:1966)
    at android.os.Parcel.readException(Parcel.java:1934)
    at android.os.Parcel.readException(Parcel.java:1884)
    at android.app.admin.IDevicePolicyManager$Stub$Proxy.addOverrideApn(IDevicePolicyManager.java:11791)
    at android.app.admin.DevicePolicyManager.addOverrideApn(DevicePolicyManager.java:10785)
    at com.example.myapplication.MainActivity.onCreate(MainActivity.java:54)
    at android.app.Activity.performCreate(Activity.java:7353)
    at android.app.Activity.performCreate(Activity.java:7344)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1275)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3140)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3303) 
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) 
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) 
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1991) 
    at android.os.Handler.dispatchMessage(Handler.java:106) 
    at android.os.Looper.loop(Looper.java:216) 
    at android.app.ActivityThread.main(ActivityThread.java:7258) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:975) 
    Caused by: android.os.RemoteException: Remote stack trace:
    at com.android.server.devicepolicy.DevicePolicyManagerService.getActiveAdminWithPolicyForUidLocked(DevicePolicyManagerService.java:3080)
    at com.android.server.devicepolicy.DevicePolicyManagerService.getActiveAdminForCallerLocked(DevicePolicyManagerService.java:3017)
    at com.android.server.devicepolicy.DevicePolicyManagerService.addOverrideApn(DevicePolicyManagerService.java:14120)
    at android.app.admin.IDevicePolicyManager$Stub.onTransact(IDevicePolicyManager.java:4339)
    at android.os.Binder.execTransact(Binder.java:739)
    Process 24556 terminated.

The error occurring in the following line.

devicePolicyManager.addOverrideApn(componentName,apn);

As per my knowledge, I need to use addOverrideApn() method to create this mobile application. So What should I do for that?


Solution

  • Your app needs to be Device Owner to use addOverrideApn(). Device Owner was first introduced in Lollipop to replace Device Admin and is intended to be used for Mobile Device Management (MDM) applications. You can activate it using adb for development / personal use but otherwise it must be activated during the setup wizard to prevent malicious admin apps from being installed via the Play store.