/* * Copyright (C) 2015 QK Labs * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.moez.QKSMS.mmssms; import android.content.Context; import android.content.res.XmlResourceParser; import android.preference.PreferenceManager; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Log; import com.moez.QKSMS.R; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; public class ApnUtils { @SuppressWarnings("unused") private static final String TAG = "ApnUtils"; @SuppressWarnings("unused") private static final boolean LOCAL_LOGV = false; public static String[] getSimOperatorCodes(Context context) { TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); String simOperator = telephonyManager.getSimOperator(); String[] mccmnc = new String[]{ null, null }; if (!TextUtils.isEmpty(simOperator)) { mccmnc[0] = simOperator.substring(0, 3); mccmnc[1] = simOperator.substring(3); } return mccmnc; } public static String[] getNetworkOperatorCodes(Context context) { TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); String simOperator = telephonyManager.getNetworkOperator(); String[] mccmnc = new String[]{ null, null }; if (!TextUtils.isEmpty(simOperator)) { mccmnc[0] = simOperator.substring(0, 3); mccmnc[1] = simOperator.substring(3); } return mccmnc; } /** * Query for apns using mcc and mnc codes found on the sim card or in the network settings. * * @param context context */ public static List<Apn> query(Context context) { String[] simCodes = getSimOperatorCodes(context); String[] networkCodes = getNetworkOperatorCodes(context); Set<Apn> resultSet = new HashSet<>(); resultSet.addAll(query(context, simCodes[0], simCodes[1])); resultSet.addAll(query(context, networkCodes[0], networkCodes[1])); List<Apn> result = new ArrayList<>(resultSet.size()); result.addAll(resultSet); return result; } /** * Query for apns using mcc and mnc codes found on the sim card or in the network settings. * * @param mcc mobile country code * @param mnc mobile network code * @param context context */ @SuppressWarnings("TryFinallyCanBeTryWithResources") public static List<Apn> query(Context context, String mcc, String mnc) { ArrayList<Apn> result = new ArrayList<>(); if (TextUtils.isEmpty(mcc) || TextUtils.isEmpty(mnc)) { Log.e(TAG, "Invalid mcc or mnc. {mcc:\"" + mcc + "\", mnc=\"" + mnc + "\"}"); return result; } // Scan the apns master list to identify compatible APNs. XmlResourceParser parser = context.getResources().getXml(R.xml.apns); try { int eventType = parser.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT) { if (isAPNStartTag(parser) && matches(parser, mcc, mnc)) { Apn apn = apnFromParser(parser); // Don't return duplicates! if (!result.contains(apn)) { result.add(apn); } } eventType = parser.next(); } } catch (XmlPullParserException|IOException e) { Log.e(TAG, "Exception thrown while getting APNs", e); } finally { parser.close(); } return result; } /** * Searches the attributes of this tag to determine if * * 1) this is an mms apn tag; and * 2) the mcc and mnc match */ private static boolean matches(XmlPullParser parser, String mcc, String mnc) { boolean mccMatches = false; boolean mncMatches = false; boolean isMMSType = false; for (int i = 0; i < parser.getAttributeCount(); i++) { String name = parser.getAttributeName(i); String value = parser.getAttributeValue(i); if ("mcc".equals(name) && mcc.equals(value)) { mccMatches = true; } else if ("mnc".equals(name) && mnc.equals(value)) { mncMatches = true; } else if ("type".equals(name) && !TextUtils.isEmpty(value) && value.contains("mms")) { isMMSType = true; } } return mccMatches && mncMatches && isMMSType; } private static Apn apnFromParser(XmlPullParser parser) { Apn apn = new Apn(); String port = null; for (int i = 0; i < parser.getAttributeCount(); i++) { String name = parser.getAttributeName(i); String value = parser.getAttributeValue(i); switch (name) { case "mmsc": apn.mmsc = value; break; case "mmsproxy": apn.proxy = value; break; case "mmsport": apn.port = value; break; case "carrier": apn.name = value; break; case "port": port = value; break; } } // Some apn listings don't use the mmsport attribute, but rather the port // attribute. // grep ' type=".*mms.*"' apns.xml | grep -v 'mmsport' | grep 'port' if (TextUtils.isEmpty(apn.port)) { apn.port = port; } return apn; } private static boolean isAPNStartTag(XmlPullParser parser) throws XmlPullParserException { return XmlPullParser.START_TAG == parser.getEventType() && "apn".equals(parser.getName()); } /** * Saves the APN information to SharedPreferences. * * @param context context * @param apn the apn to save */ public static void persistApn(Context context, Apn apn) { PreferenceManager.getDefaultSharedPreferences(context) .edit() .putString("mmsc_url", apn.mmsc) .putString("mms_proxy", apn.proxy) .putString("mms_port", apn.port) .apply(); } }