11

我在 Android v4.2 中读取 APN时遇到问题(是读取,而不是写入 APNS),它引发了安全异常:

没有写入 APN 设置的权限:用户 10068 和当前进程都没有 android.permission.WRITE_APN_SETTINGS。

以前的所有平台都使用相同的代码,有没有人知道解决这个问题的方法?

谢谢!

4

4 回答 4

13

如果您想阅读适用于 Android 4.2 及更多版本的 APN,则需要进行更改。我测试了,它的工作。

在 Android 4.1 及以下使用这个:

Cursor c = getContentResolver().query(Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current"), null, null, null, null);

对于 Android 4.2 及更高版本,请使用以下代码:

private static final String[] APN_PROJECTION = {
     Telephony.Carriers.TYPE,            // 0
     Telephony.Carriers.MMSC,            // 1
     Telephony.Carriers.MMSPROXY,        // 2
     Telephony.Carriers.MMSPORT          // 3
 };

而这一行:

final Cursor apnCursor =SqliteWrapper.query(context, this.context.getContentResolver(), Uri.withAppendedPath(Carriers.CONTENT_URI, "current"), APN_PROJECTION, null, null, null);

SQLiteWrapperClass 是隐藏的(在互联网上找到这个类)

import android.database.sqlite.SqliteWrapper;

我的英语不太好,抱歉。

于 2013-09-19T14:14:10.327 回答
8

这似乎是一种有意的改变。他们添加此防御的git commit包括以下评论:

由于数据库可能包含公司密码,我们应该保护它。使用与写入数据库相同的权限作为读取可能与写入一样具有破坏性。

可以想象,你的问题会导致他们考虑添加单独的读取权限,但至少目前,这是 4.2 的回归。

于 2012-11-19T13:14:06.380 回答
3

您可以从 /etc/apns-conf.xml 读取默认设置:

private boolean getSettingsFromApnsFile(Context context, String apnName) {
    FileReader reader = null;
    boolean sawValidApn = false;

    try {
        reader = new FileReader("/etc/apns-conf.xml");

        XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
        factory.setNamespaceAware(true);
        XmlPullParser xpp = factory.newPullParser();
        xpp.setInput(reader);

        TelephonyManager telephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
        String simOperator = telephonyManager.getSimOperator();
        if (TextUtils.isEmpty(simOperator)) {
            logger.warn("unable to get sim operator - so unable to get mms config");
            return false;
        }

        int eventType = xpp.getEventType();
        while (eventType != XmlPullParser.END_DOCUMENT) {
            if (eventType == XmlPullParser.START_TAG && xpp.getName().equals("apn")) {
                HashMap<String, String> attributes = new HashMap<String, String>();
                for (int i=0; i<xpp.getAttributeCount(); i++) {
                    attributes.put(xpp.getAttributeName(i), xpp.getAttributeValue(i));
                }
                if (attributes.containsKey("mcc") && attributes.containsKey("mnc") && simOperator.equals(attributes.get("mcc")+attributes.get("mnc"))) {
                    if (!TextUtils.isEmpty(apnName) && !apnName.trim().equals(attributes.get("apn"))) {
                        eventType = xpp.next();
                        continue;
                    }

                    if (isValidApnType(attributes.get("type"), PhoneConstants.APN_TYPE_MMS)) {
                        sawValidApn = true;

                        String mmsc = attributes.get("mmsc");
                        if (mmsc == null) {
                            eventType = xpp.next();
                            continue;
                        }

                        mServiceCenter = NetworkUtil.trimV4AddrZeros(mmsc.trim());
                        mProxyAddress = NetworkUtil.trimV4AddrZeros(
                                attributes.get("mmsproxy"));
                        if (isProxySet()) {
                            String portString = attributes.get("mmsport");
                            try {
                                mProxyPort = Integer.parseInt(portString);
                            } catch (NumberFormatException e) {
                                if (TextUtils.isEmpty(portString)) {
                                    logger.warn("mms port not set!");
                                } else {
                                    logger.error("Bad port number format: " + portString, e);
                                }
                            }
                        }
                    }

                }
            }
            eventType = xpp.next();
        }
    } catch (Exception e) {
        logger.warn("unable to get mmsc config from apns-conf file", e);
    } finally {
        if (reader != null) {
            try {
                reader.close();
            } catch (Exception e) {
            }
        }
    }
    return sawValidApn;
}
于 2013-11-26T14:34:24.853 回答
-6

我也有这种情况,我的解决方案是不要在 AsyncTask 中访问 android_assets。"确保只有您的主线程有权访问您应用的 assets 目录"

当我像这样编码时遇到了问题:

@Override
protected void onResume() {
    super.onResume();
    //mWebView.loadUrl("file:///android_asset/95306.html");
    new LoadUrlTask().execute("file:///android_asset/95306.html");
}

...

class LoadUrlTask extends AsyncTask<String, Integer , String> {
    // progressDialog = new ProgressDialog(LoadActivity.this);

    @Override
    protected String doInBackground(String... strings) {
        mWebView.loadUrl(strings[0]);
        return "";
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        //progressDialog.dismiss();
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        //progressDialog.setMessage("loading...");
        //progressDialog.show();
    }
}

我通过以下方式修复它:

@Override
protected void onResume() {
    super.onResume();
    mWebView.loadUrl("file:///android_asset/95306.html");
    //new LoadUrlTask().execute("file:///android_asset/95306.html");
}

希望对你有帮助!

于 2014-10-20T02:03:24.940 回答