package com.klinker.android.send_message;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.content.res.XmlResourceParser;
import android.os.Build;
import android.preference.PreferenceManager;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import android.telephony.cdma.CdmaCellLocation;
import android.widget.Toast;
import com.klinker.android.logger.Log;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.ArrayList;
public class ApnUtils {
private static final String TAG = "ApnUtils";
public static void initDefaultApns(final Context context, final OnApnFinishedListener listener) {
loadMmsSettings(context);
final ArrayList<APN> apns = loadApns(context);
if (apns == null || apns.size() == 0) {
Log.v(TAG, "Found no APNs :( Damn CDMA network probably.");
Toast.makeText(context, context.getString(R.string.auto_select_failed), Toast.LENGTH_SHORT).show();
if (listener != null) {
listener.onFinished();
}
} else if (apns.size() == 1) {
setApns(context, apns.get(0));
if (listener != null) {
listener.onFinished();
}
} else {
if (!PreferenceManager.getDefaultSharedPreferences(context).getBoolean("has_seen_select_apns_warning", false)) {
new AlertDialog.Builder(context)
.setTitle(R.string.auto_select_apn)
.setMessage(R.string.auto_select_multiple_apns)
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int num) {
showApnChooser(context, apns, listener);
}
})
.show();
PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean("has_seen_select_apns_warning", true).commit();
} else {
showApnChooser(context, apns, listener);
}
}
}
private static void showApnChooser(final Context context, final ArrayList<APN> apns, final OnApnFinishedListener listener) {
CharSequence[] items = new CharSequence[apns.size()];
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
String curMmsc = sharedPrefs.getString("mmsc_url", "");
String curProxy = sharedPrefs.getString("mms_proxy", "");
String curPort = sharedPrefs.getString("mms_port", "");
int defaultApn = -1;
for (int i = 0; i < items.length; i++) {
APN apn = apns.get(i);
items[i] = (i+1) + ". " + apn.name;
if (apn.mmsc.equals(curMmsc) && apn.proxy.equals(curProxy) && apn.port.equals(curPort)) {
defaultApn = i;
}
}
new AlertDialog.Builder(context)
.setSingleChoiceItems(items, defaultApn, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
setApns(context, apns.get(i));
if (listener != null) {
listener.onFinished();
}
dialogInterface.dismiss();
}
})
.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialogInterface) {
if (listener != null) {
listener.onFinished();
}
}
})
.show();
}
public interface OnApnFinishedListener {
public abstract void onFinished();
}
private static void loadMmsSettings(Context context) {
XmlResourceParser parser = context.getResources().getXml(R.xml.mms_config);
String maxMessageSize = 1000000 + "";
int maxImageHeight = 800;
int maxImageWidth = 800;
String userAgent = "Android Messaging";
String uaProfUrl = "http://www.gstatic.com/android/hangouts/hangouts_mms_ua_profile.xml";
try {
beginDocument(parser, "mms_config");
while (true) {
nextElement(parser);
String tag = parser.getName();
if (tag == null) {
break;
}
String name = parser.getAttributeName(0);
String value = parser.getAttributeValue(0);
String text = null;
if (parser.next() == XmlPullParser.TEXT) {
text = parser.getText();
}
Log.v(TAG, "tag: " + tag + " value: " + value + " - " +
text);
if ("name".equalsIgnoreCase(name)) {
if ("int".equals(tag)) {
// int config tags go here
if ("maxMessageSize".equalsIgnoreCase(value)) {
maxMessageSize = text;
} else if ("maxImageHeight".equalsIgnoreCase(value)) {
maxImageHeight = Integer.parseInt(text);
} else if ("maxImageWidth".equalsIgnoreCase(value)) {
maxImageWidth = Integer.parseInt(text);
}
} else if ("string".equals(tag)) {
// string config tags go here
if ("userAgent".equalsIgnoreCase(value)) {
userAgent = text;
} else if ("uaProfUrl".equalsIgnoreCase(value)) {
uaProfUrl = text;
}
}
}
}
} catch (XmlPullParserException e) {
Log.e(TAG, "loadMmsSettings caught ", e);
} catch (NumberFormatException e) {
Log.e(TAG, "loadMmsSettings caught ", e);
} catch (IOException e) {
Log.e(TAG, "loadMmsSettings caught ", e);
} finally {
parser.close();
}
String errorStr = null;
if (errorStr != null) {
String err =
String.format("MmsConfig.loadMmsSettings mms_config.xml missing %s setting",
errorStr);
Log.e(TAG, err);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
final TelephonyManager telephonyManager =
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
userAgent = telephonyManager.getMmsUserAgent();
uaProfUrl = telephonyManager.getMmsUAProfUrl();
}
PreferenceManager.getDefaultSharedPreferences(context)
.edit()
.putInt("mms_max_width", maxImageWidth)
.putInt("mms_max_height", maxImageHeight)
.putString("mms_max_size", maxMessageSize)
.putString("mms_agent", userAgent)
.putString("mms_user_agent_profile_url", uaProfUrl)
.commit();
}
private static ArrayList<APN> loadApns(Context context) {
XmlResourceParser parser = context.getResources().getXml(R.xml.apns);
ArrayList<APN> apns = new ArrayList<APN>();
String mmsc = "", proxy = "", port = "", carrier = "";
int mcc = -1, mnc = -1;
TelephonyManager manager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
String networkOperator = manager.getNetworkOperator();
if (isValidNetworkOperator(networkOperator)) {
mcc = Integer.parseInt(networkOperator.substring(0, 3));
String s = networkOperator.substring(3);
try {
mnc = Integer.parseInt(s.replaceFirst("^0{1,2}", ""));
} catch (Exception e) {
mnc = -1;
}
} else {
mcc = context.getResources().getConfiguration().mcc;
mnc = context.getResources().getConfiguration().mnc;
}
try {
if (mcc == -1) {
mcc = Integer.parseInt(new ServiceState().getOperatorNumeric().substring(0, 3));
}
if (mnc == -1) {
TelephonyManager tm = (TelephonyManager) context.getSystemService
(Context.TELEPHONY_SERVICE);
mnc = ((CdmaCellLocation) tm.getCellLocation()).getSystemId();
}
} catch (Exception e) {
}
if (mcc == -1 || mnc == -1) {
Log.v(TAG, "couldn't find both mcc and mnc. mcc = " + mcc + ", mnc = " + mnc);
return null;
}
Log.v(TAG, "mcc: " + mcc + " mnc: " + mnc);
try {
beginDocument(parser, "apns");
while (true) {
nextElement(parser);
String tag = parser.getName();
if (tag == null) {
break;
}
boolean mccCorrect = false, mncCorrect = false;
for (int i = 0; i < parser.getAttributeCount(); i++) {
try {
String name = parser.getAttributeName(i);
int value = Integer.parseInt(parser.getAttributeValue(i));
if ("mcc".equals(name) && mcc == value) {
mccCorrect = true;
} else if ("mnc".equals(name) && mnc == value) {
mncCorrect = true;
}
} catch (Exception e) {
// cast exception probably
}
}
if (mccCorrect && mncCorrect) {
// parse the rest of the apn
for (int i = 0; i < parser.getAttributeCount(); i++) {
String name = parser.getAttributeName(i);
String value = parser.getAttributeValue(i);
if ("type".equals(name)) {
if (!value.contains("mms")) {
mmsc = "";
proxy = "";
port = "";
break;
}
} else if ("mmsc".equals(name)) {
mmsc = value;
} else if ("mmsproxy".equals(name)) {
proxy = value;
} else if ("mmsport".equals(name)) {
port = value;
} else if ("carrier".equals(name)) {
carrier = value;
} else if ("port".equals(name) && port.equals("")) {
port = value;
}
}
if (!mmsc.equals("")) {
APN apn = new APN();
apn.name = carrier;
apn.mmsc = mmsc;
apn.proxy = proxy;
apn.port = port;
boolean contains = false;
for (int i = 0; i < apns.size(); i++) {
APN current = apns.get(i);
if (current.mmsc.equals(apn.mmsc) && current.port.equals(apn.port) && current.proxy.equals(apn.proxy)) {
contains = true;
break;
}
}
if (!contains) {
apns.add(apn);
}
}
}
}
} catch (XmlPullParserException e) {
Log.e(TAG, "loadApns caught ", e);
} catch (NumberFormatException e) {
Log.e(TAG, "loadApns caught ", e);
} catch (IOException e) {
Log.e(TAG, "loadApns caught ", e);
} finally {
parser.close();
}
Log.v(TAG, "MMSC: " + mmsc + ", MMS Proxy: " + proxy + ", MMS Port: " + port);
String errorStr = null;
if (errorStr != null) {
String err =
String.format("MmsConfig.loadMmsSettings mms_config.xml missing %s setting",
errorStr);
Log.e(TAG, err);
}
return apns;
}
/**
* Checks if the given network operator is valid, i.e. it's not null, empty or contains "null"
*
* @param networkOperator
* The network operator to be checked
*
* @return True if is a valid operator
*/
private static boolean isValidNetworkOperator(String networkOperator) {
return networkOperator != null && !networkOperator.isEmpty() &&
!networkOperator.contains("null");
}
private static void setApns(Context context, APN apn) {
PreferenceManager.getDefaultSharedPreferences(context)
.edit()
.putString("mmsc_url", apn.mmsc)
.putString("mms_proxy", apn.proxy)
.putString("mms_port", apn.port)
.commit();
}
private static void beginDocument(XmlPullParser parser, String firstElementName) throws XmlPullParserException, IOException {
int type;
while ((type=parser.next()) != parser.START_TAG
&& type != parser.END_DOCUMENT) {
;
}
if (type != parser.START_TAG) {
throw new XmlPullParserException("No start tag found");
}
if (!parser.getName().equals(firstElementName)) {
throw new XmlPullParserException("Unexpected start tag: found " + parser.getName() +
", expected " + firstElementName);
}
}
private static void nextElement(XmlPullParser parser) throws XmlPullParserException, IOException {
int type;
while ((type=parser.next()) != parser.START_TAG
&& type != parser.END_DOCUMENT) {
;
}
}
private static class APN {
public String name;
public String mmsc;
public String proxy;
public String port;
}
}