Android 阅读安卓4.2中的APNs?

Android 阅读安卓4.2中的APNs?,android,apn,Android,Apn,我在Android v4.2中读取APN时遇到问题(是读取,不是写入APN),它引发了一个安全异常: 没有写入APN设置的权限:用户10068和当前 进程具有android.permission.WRITE\u APN\u设置 以前所有平台上都使用相同的代码,有人知道有什么解决方法吗 谢谢 这似乎是有意的改变。报告包括以下评论: 由于数据库可能包含公司密码,我们应该保护它。使用与写入DB相同的权限进行读取可能与写入一样有害 可以想到,你的问题会导致他们考虑添加一个单独的读权限,但至少暂时来说,这

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

没有写入APN设置的权限:用户10068和当前 进程具有android.permission.WRITE\u APN\u设置

以前所有平台上都使用相同的代码,有人知道有什么解决方法吗


谢谢

这似乎是有意的改变。报告包括以下评论:

由于数据库可能包含公司密码,我们应该保护它。使用与写入DB相同的权限进行读取可能与写入一样有害


可以想到,你的问题会导致他们考虑添加一个单独的读权限,但至少暂时来说,这是一个4.2的回归。

< P>如果你想读取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是隐藏的(在internet中找到该类)


我的英语不太好,抱歉。

您可以从/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;
}
private boolean getSettingsFromApnsFile(上下文,字符串名称){
FileReader=null;
布尔值sawValidApn=false;
试一试{
reader=newfilereader(“/etc/apns-conf.xml”);
XmlPullParserFactory工厂=XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp=factory.newPullParser();
设置输入(读卡器);
TelephonyManager TelephonyManager=(TelephonyManager)context.getSystemService(context.TELEPHONY_服务);
字符串simOperator=telephonyManager.getSimOperator();
if(TextUtils.isEmpty(simOperator)){
logger.warn(“无法获取sim卡运营商-因此无法获取彩信配置”);
返回false;
}
int eventType=xpp.getEventType();
while(eventType!=XmlPullParser.END_文档){
if(eventType==XmlPullParser.START_标记&&xpp.getName().equals(“apn”)){
HashMap attributes=新的HashMap();

对于(int i=0;i我也有这种情况,我的解决方案是在AsyncTask中不访问android_资产。”确保只有主线程有权访问应用程序的资产目录。”

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

@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();
    }
}

希望这能对您有所帮助!

这听起来像是一个bug,或者是一种保护APN数据的笨拙方法(在这种情况下,应该有一个专用的
读取APN\u设置
权限)。我没有看到这方面的问题,所以如果你能创建一个项目来复制错误,将它和说明发布到。完成后,你可以在这里检查它。希望相同的解决方案可以应用于读取和写入APN。希望在4.2被其他制造商接受之前。称我为梦想家。我把我的应用程序放进去了/系统/应用程序,我仍然收到此错误。是否应将此权限授予系统文件夹中的任何应用程序或由OEM签署?对于所有使用移动数据执行操作(如发送彩信)的应用程序,有什么替代方案并且无法知道设备中的默认APN设置是什么?@toobsco42:我不知道。你可能想打开一个新的StackOverflow问题,看看是否有人有解决方案。但这不是sdk的一部分,它可能无法在所有android设备上工作,你不这样认为吗?是的,现在我知道HTC已经删除了至少一台设备上的文件。这就是这只是Android上默认APN配置的列表。正如@Shatazone提到的,它依赖于手机。配置不依赖于手机。每个ROM上只有文件不同(在aosp git中经常更改)。这只是android bug的一个解决方法。你也可以在你的应用程序中提供更为最新的版本。就像我们一样。嗨。我在导入android.provider.Telephony.Carriers时遇到了问题,即使android文档说它自API 19以来是公共的。我如何导入它?在API 19中,这不是问题。Carriers类可用于此import import android.provider.Telephony;如果不起作用,则将源代码中的java类导入src文件夹。我必须更新sdk,然后它才起作用。但是,除了您使用SqliteWrapper报告的字段外,我在读取某些字段时遇到了问题(尽管第一种方法对我不起作用)在中报告的字段中,似乎只有以下字段是可读的:Telephony.Carriers.APN、Telephony.Carriers.MMSPROXY、Telephony.Carriers.MMSPORT、Telephony.Carriers.MMSC、Telephony.Carriers.TYPE我是否缺少权限(我已读取\u APN\u设置)还是做错了什么?@ashish你找到解决方案了吗?Yuppeerr。这很有效。在三星Galaxy S4 5.0.1上进行了测试。谢谢,伙计:):D:D这应该有什么帮助。你的答案超出了问题的范围,与访问APN设置无关。
@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");
}