简体   繁体   中英

How to give system level permissions programatically in android?

I am trying to read existing APN and then need to write custum APN name in my android device. But it is not allowing me to read/write even I put my app in /system/app and declare below permissions in my manifest.

throws below error

15:01:17.831: W/System.err(1717): java.lang.SecurityException: Neither user 10060 nor current process has android.permission.MODIFY_PHONE_STATE. 01-01 15:01:17.832: W/System.err(1717): at android.os.Parcel.readException(Parcel.java:1620) 01-01 15:01:17.832: W/System.err(1717): at android.os.Parcel.readException(Parcel.java:1573) 01-01 15:01:17.832: W/System.err(1717): at com.android.internal.telephony.ITelephony$Stub$Proxy.supplyPin(ITelephony.java:1775) 01-01 15:01:17.833: W/System.err(1717): at com.intel.sunnypoint.headless.HeadlessService.simUnlock(HeadlessService.java:194) 01-01 15:01:17.833: W/System.err(1717): at com.intel.sunnypoint.headless.HeadlessService.onStartCommand(HeadlessService.java:166) 01-01 15:01:17.833: W/System.err(1717): at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3032) 01-01 15:01:17.833: W/System.err(1717): at android.app.ActivityThread.access$2300(ActivityThread.java:150) 01-01 15:01:17.833: W/System.err(1717): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1455) 01-01 15:01:17.833: W/System.err(1717): at android.os.Handler.dispatchMessage(Handler.java:102) 01 -01 15:01:17.833: W/System.err(1717): at android.os.Looper.loop(Looper.java:148) 01-01 15:01:17.833: W/System.err(1717): at android.app.ActivityThread.main(ActivityThread.java:5446) 01-01 15:01:17.833: W/System.err(1717): at java.lang.reflect.Method.invoke(Native Method) 01-01 15:01:17.833: W/System.err(1717): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:749) 01-01 15:01:17.833: W/System.err(1717): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:639)

Below is my code

public int InsertAPN(String name){

    //Set the URIs and variables
    int id = -1;
    boolean existing = false;
    final Uri APN_TABLE_URI = Uri.parse("content://telephony/carriers");
    final Uri PREFERRED_APN_URI = Uri.parse("content://telephony/carriers/preferapn");

    //Check if the specified APN is already in the APN table, if so skip the insertion
    Cursor parser = getContentResolver().query(APN_TABLE_URI, null, null, null, null);
    parser.moveToLast();
    while (parser.isBeforeFirst() == false){
        int index = parser.getColumnIndex("name");
        String n = parser.getString(index);
        if (n.equals(name)) {
            existing = true;
            Log.d(TAG, "APN already configured.");
            break;
        }
        parser.moveToPrevious();
    }

    //if the entry doesn't already exist, insert it into the APN table
    if (!existing){

        //Initialize the Content Resolver and Content Provider
        ContentResolver resolver = this.getContentResolver();
        ContentValues values = new ContentValues();

        //Capture all the existing field values excluding name
        Cursor apu = getContentResolver().query(PREFERRED_APN_URI, null, null, null, null);
        apu.moveToFirst();


        //Assign them to the ContentValue object
        values.put("name", name); //the method parameter
        values.put("apn", "Simple CMW APN");
        values.put("type", "default");
        values.put("proxy", "");
        values.put("port", "");
        values.put("user", "");
        values.put("password", "");
        values.put("server", "");
        values.put("mmsc", "");
        values.put("mmsproxy", "");
        values.put("mmsport", "");
        values.put("mcc", "001");
        values.put("mnc", "01");
        values.put("numeric", "");

        //Actual insertion into table
        Cursor c = null;
        try{
            Uri newRow = resolver.insert(APN_TABLE_URI, values);

            if(newRow != null){
                c = resolver.query(newRow, null, null, null, null);
                int idindex = c.getColumnIndex("_id");
                c.moveToFirst();
                id = c.getShort(idindex);
            }
        }
        catch(Exception e){}
        if(c !=null ) c.close();
    }

    return id;
}

//Takes the ID of the new record generated in InsertAPN and sets that particular record the default preferred APN configuration
public boolean SetPreferredAPN(int id){

    //If the id is -1, that means the record was found in the APN table before insertion, thus, no action required
    if (id == -1){
        return false;
    }

    Uri.parse("content://telephony/carriers");
    final Uri PREFERRED_APN_URI = Uri.parse("content://telephony/carriers/preferapn");

    boolean res = false;
    ContentResolver resolver = this.getContentResolver();
    ContentValues values = new ContentValues();

    values.put("apn_id", id);
    try{
        resolver.update(PREFERRED_APN_URI, values, null, null);
        Cursor c = resolver.query(PREFERRED_APN_URI, new String[]{"name", "apn"}, "_id="+id, null, null);
        if(c != null){
            res = true;
            c.close();
        }
    }
    catch (Exception e){}
    return res;
}

Please guide me how to set it. Thanks in advance.

For permissions classified as 'dangerous' you need to request the permission from the user, just putting them in the manifest will not accomplish this.

Refer to https://developer.android.com/training/permissions/requesting.html

If you need help setting that up let me know :)

If you will read in documentation, you can see that:

MODIFY_PHONE_STATE

Allows modification of the telephony state - power on, mmi, etc. Does not include placing calls.

Not for use by third-party applications.

Please, pay attention at last line. It is permission that only may be used by system and not by others application.

System level applications are pre-installed into a system folder or compiled with a special manufacturer's certificate. You said you put it in /system/app folder but you should understand that only users of rooted devices can repeat your steps. Of course, you will not be able to achieve this goal publishing your app into Google Play.

Overall, it looks like you are trying to use some hidden API. You should look on other ways to achieve this goal. Probably, it is not allowed to change APNs programmatically, but I am not sure.

1.You need to sign your application in the same key the system is signed

2.You need your app to have the system uid in android manifest

3.SELinux policy, if enforced need to allow that operation, in your case I think it will have no problem

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM