Question

I am attempting to update the 'name' column of the preferred APN database table found in the location: content://telephony/carriers/preferapn. However, my application's ContentResolver.update() always returns 0, meaning no rows have been updated. I already have root access for the application and confirmed it programmatically prior to running update().

Details about the table columns can be found here and here. I also made sure to reference the documentation on how the update function is called.

The update method:

public boolean setAPN(String newAPN, TextView t){

    //get URI objects for the tables
    final Uri APN_TABLE_URI = Uri.parse("content://telephony/carriers");
    final Uri PREFERRED_APN_URI = Uri.parse("content://telephony/carriers/preferapn");

    //Confirm permissions
    PackageManager pm = getPackageManager();
    if (pm.checkPermission(permission.WRITE_APN_SETTINGS, getPackageName()) == PackageManager.PERMISSION_GRANTED) {

        //Update name field
        ContentResolver resolver = this.getContentResolver();
        ContentValues values = new ContentValues();          
        values.put("name", newAPN);
        long rc = resolver.update(PREFERRED_APN_URI, values, null, null);

        //Display the row contents (always has the original fields, doesn't update)
        Cursor c = getContentResolver().query(PREFERRED_APN_URI, null, null, null, null);
        c.moveToFirst();         
        int index = c.getColumnIndex("_id");    //getting index of required column
        Short id = c.getShort(index);           //getting APN's id from        
        index = c.getColumnIndex("name");
        String name = c.getString(index);        
        index = c.getColumnIndex("mcc");
        String mcc = c.getString(index);        
        index = c.getColumnIndex("mnc");
        String mnc = c.getString(index);        
        index = c.getColumnIndex("numeric");
        String numeric = c.getString(index);

        t.setText(" ID:" + id + "\n" + 
              " APN Name: " + name + "\n" +
              " MCC: " + mcc + "\n" +
              " MNC: " + mnc + "\n" +
              " Numeric: " + numeric + "\n"

            );

    } else { 
        t.setText(" You don't have permission to do this. ");    
    }

    return true;
}

As previously mentioned, I also have the permission: "android.permission.WRITE_APN_SETTINGS" in the manifest file:

Have I called the update function incorrectly for my particular purpose? Or is using update() the wrong way to go about this?

Was it helpful?

Solution

This question's been dead for almost a month now, but I made a workaround for this issue and wanted to share it. The workaround consists of copying the existing preferred APN entry excluding the name field, inserting the new APN into the carrier list, then setting the new APN as preferred using the newly generated id.

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;   
            Toast.makeText(getApplicationContext(), "APN already configured.",Toast.LENGTH_SHORT).show();
            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();                   
           int index;       

           index = apu.getColumnIndex("apn");
           String apn = apu.getString(index);               
           index = apu.getColumnIndex("type");
           String type = apu.getString(index);              
           index = apu.getColumnIndex("proxy");
           String proxy = apu.getString(index);             
           index = apu.getColumnIndex("port");
           String port = apu.getString(index);               
           index = apu.getColumnIndex("user");
           String user = apu.getString(index);              
           index = apu.getColumnIndex("password");
           String password = apu.getString(index);              
           index = apu.getColumnIndex("server");
           String server = apu.getString(index);                
           index = apu.getColumnIndex("mmsc");
           String mmsc = apu.getString(index);             
           index = apu.getColumnIndex("mmsproxy");
           String mmsproxy = apu.getString(index);              
           index = apu.getColumnIndex("mmsport");
           String mmsport = apu.getString(index);               
           index = apu.getColumnIndex("mcc");
           String mcc = apu.getString(index);               
           index = apu.getColumnIndex("mnc");
           String mnc = apu.getString(index);               
           index = apu.getColumnIndex("numeric");
           String numeric = apu.getString(index);

           //Assign them to the ContentValue object
           values.put("name", name); //the method parameter
           values.put("apn", apn);                 
           values.put("type", type);
           values.put("proxy", proxy);
           values.put("port", port);
           values.put("user", user);
           values.put("password", password);
           values.put("server", server);
           values.put("mmsc", mmsc);
           values.put("mmsproxy", mmsproxy);
           values.put("mmsport", mmsport);             
           values.put("mcc", mcc);
           values.put("mnc", mnc);
           values.put("numeric", 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(SQLException 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 (SQLException e){}
     return res;
}

You can then call the method like so:

int identity = InsertAPN(NEW_APN_NAME); 
SetPreferredAPN(identity);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top