Android OTA升级后更新APN参数的实现

前言:最近在Android8.0的项目中遇到一个新的需求,客户在MR版本中要求我们更改APN参数,然后通过OTA升级的方式来更新APN参数,但是Android系统的设计是只有第一次刷机后开机才会走APN的初始化,并将APN添加到数据库中,OTA升级是不会触发系统去更新数据库的。

1、首先定义了一个BroadcastReceiver用于接收系统开机的广播,代码如下,注释见代码

public class ResetApnReceiver extends BroadcastReceiver {

    private static final String TAG = "Felix ResetApnReceiver";
    private static final String ACTION_BOOT = "android.intent.action.BOOT_COMPLETED";

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i(TAG, "onReceive");
        if (ACTION_BOOT.equals(intent.getAction())) {
            Log.i(TAG, "receive boot completed");
            SharedPreferences sp = context.getSharedPreferences("updateApn",
                    Context.MODE_PRIVATE);
            //获取当前的系统版本号
            String version = sp.getString("version", "");
            //判断系统是否发生了升级  避免每次开机后遍历xml导致系统性能降低
            if (!version.equals(SystemProperties.get("ro.internal.build.version"))) {
                context.startService(new Intent(context, ResetApnService.class));
                Log.i(TAG, "service start, version:" + version);
                //保存系统版本号
                sp.edit().putString("version", SystemProperties.get("ro.internal.build.version")).commit();
            } else {
                Log.i(TAG, "not start service, version:" + version);
            }
        }
    }
}

由于上面的代码很简单,就不做过多的解释了,主要就是判断系统版本是否发生了升级,若发生了升级,就开启服务去遍历xml并更新到数据库,若未升级则不遍历。

2、接下来我们来看看Service的实现,思路很简单,遍历新的apns-conf.xml文件,然后去数据库做对比,查询数据是否发生了更改,若更改则将最新的参数同步到数据库保存,否则就不管。

public class ResetApnService extends Service {

    private static final String APN_PATH = "/system/etc/apns-conf.xml";
    private static final String TAG = "Felix ResetApnService";
    public static final Uri CONTENT_URI = Uri.parse("content://telephony/carriers");
    private FileInputStream fis;
    private int updateId;

    public ResetApnService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        writeApn();
    }

    private void writeApn() {
        Log.i(TAG, "writeApn()");
        new Thread() {
            @Override
            public void run() {
                try {
                    Log.i(TAG, "start parser");
                    //parser apns-conf.xml
                    XmlPullParser parser = Xml.newPullParser();
                    fis = new FileInputStream(APN_PATH);
                    Log.i(TAG, "file to stream");
                    parser.setInput(fis, "utf-8");
                    Log.i(TAG, "set utf-8");
                    int eventType = parser.getEventType();
                    while (eventType != XmlPullParser.END_DOCUMENT) {
                        switch (eventType) {
                            case XmlPullParser.START_TAG:
                                String name = parser.getName();
                                if ("apn".equalsIgnoreCase(name)) {
                                    //mcc_number:客户发生更改的mcc值
                                    if ("mcc_number".equals(parser.getAttributeValue(null, "mcc"))) {
                                        int count = parser.getAttributeCount();
                                        String[] names = new String[count];
                                        String[] values = new String[count];
                                        for (int i = 0; i < count; i++) {
                                            names[i] = parser.getAttributeName(i);
                                            values[i] = parser.getAttributeValue(i);
                                            Log.i(TAG, names[i] + " : " + values[i]);
                                        }

                                        StringBuilder sb = new StringBuilder();
                                        for (int i = 0; i < names.length; i++) {
                                            if (names[i].equals("carrier")) {
                                                sb.append("name");
                                            } else {
                                                sb.append(names[i]);
                                            }
                                            sb.append("=\"");
                                            sb.append(values[i]);
                                            sb.append("\"");
                                            if (i != names.length - 1) {
                                                sb.append(" and ");
                                            }
                                        }
                                        if (!checkApn(sb.toString())) {
                                            boolean result = updateApn(CONTENT_URI,
                                                    "_id = \"" + updateId + "\"", names, values);
                                            Log.i(TAG, "update:" + result);
                                            updateId++;
                                        }
                                    }
                                }
                                break;
                            case XmlPullParser.END_TAG:
                                break;
                        }
                        eventType = parser.next();
                    }
                    Log.i(TAG, "parser end");
                    fis.close();
                    Log.i(TAG, "file close");
                    stopSelf();

                } catch (FileNotFoundException e) {
                    Log.i(TAG, "sorry, file not found!");
                    if (fis != null)
                        try {
                            fis.close();
                            stopSelf();
                        } catch (IOException e1) {
                            e1.printStackTrace();
                        }
                    e.printStackTrace();
                } catch (XmlPullParserException e) {
                    Log.i(TAG, "sorry, xml parser fail!");
                    if (fis != null)
                        try {
                            fis.close();
                            stopSelf();
                        } catch (IOException e1) {
                            e1.printStackTrace();
                        }
                    e.printStackTrace();
                } catch (IOException e) {
                    Log.i(TAG, "sorry, IO exception!");
                    if (fis != null)
                        try {
                            fis.close();
                            stopSelf();
                        } catch (IOException e1) {
                            e1.printStackTrace();
                        }
                    e.printStackTrace();
                }
            }
        }.start();
    }

    //检查apn参数是否发生了变化
    private boolean checkApn(String where) {
        Log.i(TAG, "start check apn");
        Log.i(TAG, "check where:" + where);
        Cursor cursor = getContentResolver().query(CONTENT_URI, new String[]{"_id"}, where, null, null);
        if (cursor != null) {
            boolean moveToNext = cursor.moveToNext();
            if (moveToNext) {
                updateId = Integer.valueOf(cursor.getString(0)) + 1;
            }
            Log.i(TAG, "check result:" + moveToNext);
            cursor.close();
            return moveToNext;
        }
        return true;
    }

    //更新数据
    private boolean updateApn(Uri updateURI, String where, String[] name, String[] values) {
        Log.i(TAG, "start update apn");
        Log.i(TAG, "where:" + where);
        ContentValues contentValues = new ContentValues();
        for (int i = 0; i < name.length; i++) {
            if (name[i].equals("carrier")) {
                contentValues.put("name", values[i]);
            } else {
                contentValues.put(name[i], values[i]);
            }
        }
        int update = getContentResolver().update(updateURI, contentValues, where, null);
        Log.i(TAG, "update result :" + update);
        if (update > 0) {
            return true;
        } else {
            return false;
        }
    }
}

由于代码逻辑很简单,就不做过多的赘述了,可能有些人想说,干嘛不调用系统的重置APN参数的方法,这样系统会重新去xml里面读取参数来初始化数据库,但是这样若用户自定义了APN数据则会丢失,影响用户体验。

全文完 ~

猜你喜欢

转载自blog.csdn.net/XCF95319605/article/details/81081939