com.newcell.calltext.wizards.impl.Basic.java Source code

Java tutorial

Introduction

Here is the source code for com.newcell.calltext.wizards.impl.Basic.java

Source

/**
 * Copyright (C) 2010-2012 Regis Montoya (aka r3gis - www.r3gis.fr)
 * This file is part of CSipSimple.
 *
 *  CSipSimple is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *  If you own a pjsip commercial license you can also redistribute it
 *  and/or modify it under the terms of the GNU Lesser General Public License
 *  as an android library.
 *
 *  CSipSimple is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with CSipSimple.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.newcell.calltext.wizards.impl;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.ProgressDialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.preference.EditTextPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
import android.telephony.TelephonyManager;
import android.widget.Toast;

import com.newcell.calltext.R;
import com.newcell.calltext.api.SipManager;
import com.newcell.calltext.api.SipProfile;
import com.newcell.calltext.api.SipUri;
import com.newcell.calltext.api.SipUri.ParsedSipContactInfos;
import com.newcell.calltext.utils.Log;

public class Basic extends BaseImplementation {
    protected static final String TAG = "Basic W";

    private Preference accountSync;
    private EditTextPreference accountDisplayName;
    private EditTextPreference accountUserName;
    private EditTextPreference accountServer;
    private EditTextPreference accountPassword;

    private ProgressDialog dialog;
    private Context context;
    private SharedPreferences sharedPref;
    private SharedPreferences.Editor prefEditor;

    private static final String REQUEST_AUTH = "request_authentication";
    private static final String REQUEST_INFO = "request_user_info";
    private static final String REQUEST_COMPLETE = "request_complete";
    private static final String DEF_DISPLAY_NAME = "NO ACCOUNT FOUND";
    private static final String DEF_USER_NAME = "NOACCOUNTFOUND";
    private static final String DEF_PASSWORD = "PASSWORD";

    public static final int MEID_DECIMAL_NEEDED_LENGTH = 18;

    private void bindFields() {
        accountSync = (Preference) findPreference("sync");
        accountDisplayName = (EditTextPreference) findPreference("display_name");
        accountUserName = (EditTextPreference) findPreference("username");
        accountServer = (EditTextPreference) findPreference("server");
        accountPassword = (EditTextPreference) findPreference("password");

        dialog = new ProgressDialog(context);

        // Open shared preferences for the app to retrieve AuthKey and AuthPass
        sharedPref = context.getSharedPreferences(context.getString(R.string.preference_file_key),
                Context.MODE_PRIVATE);

        prefEditor = sharedPref.edit();

        accountSync.setOnPreferenceClickListener(new OnPreferenceClickListener() {
            @Override
            public boolean onPreferenceClick(Preference preference) {
                /*
                 * Old AuthKey/AuthPass method
                    
                String temp_auth_key = 
                      sharedPref.getString(context.getString(R.string.preference_auth_key), "");
                String temp_auth_pass = 
                      sharedPref.getString(context.getString(R.string.preference_auth_pass), "");
                    
                if(temp_auth_key == null
                      || temp_auth_key == ""
                      || temp_auth_pass == null
                      || temp_auth_pass == "") {
                   // User AuthKey and AuthPass preference files 
                   // don't exist, request them
                   Log.i(TAG, "No user authentication key/password, starting REQUEST_AUTH...");
                   new AccountDownloader().execute(REQUEST_AUTH);
                } else {
                   // User AuthKey and AuthPass preference files already exist, 
                   // just request account info
                   Log.i(TAG, "User authentication key/password found, starting REQUEST_INFO...");
                   new AccountDownloader().execute(REQUEST_INFO);
                }
                    
                 * Old AuthKey/AuthPass method
                 */

                new AccountDownloader().execute(REQUEST_INFO);

                return true;
            }
        });

    }

    public void fillLayout(final SipProfile account) {

        context = parent;

        bindFields();

        accountDisplayName.setText(account.display_name);

        String serverFull = account.reg_uri;
        if (serverFull == null) {
            //serverFull = "";
            serverFull = SipManager.SERVER_DOMAIN;
        } else {
            serverFull = serverFull.replaceFirst("sip:", "");
        }

        ParsedSipContactInfos parsedInfo = SipUri.parseSipContact(account.acc_id);
        accountUserName.setText(parsedInfo.userName);
        accountServer.setText(serverFull);
        accountPassword.setText(account.data);
    }

    public void updateDescriptions() {
        setStringFieldSummary("display_name");
        setStringFieldSummary("username");
        setStringFieldSummary("server");
        setPasswordFieldSummary("password");
    }

    private static HashMap<String, Integer> SUMMARIES = new HashMap<String, Integer>() {
        /**
        * 
        */
        private static final long serialVersionUID = -5743705263738203615L;

        {
            put("display_name", R.string.w_common_display_name_desc);
            put("username", R.string.w_basic_username_desc);
            put("server", R.string.w_common_server_desc);
            put("password", R.string.w_basic_password_desc);
        }
    };

    @Override
    public String getDefaultFieldSummary(String fieldName) {
        Integer res = SUMMARIES.get(fieldName);
        if (res != null) {
            return parent.getString(res);
        }
        return "";
    }

    public boolean canSave() {
        boolean isValid = true;

        isValid &= checkField(accountDisplayName, isEmpty(accountDisplayName));
        isValid &= checkField(accountPassword, isEmpty(accountPassword));
        isValid &= checkField(accountServer, isEmpty(accountServer));
        isValid &= checkField(accountUserName, isEmpty(accountUserName));

        return isValid;
    }

    public SipProfile buildAccount(SipProfile account) {
        Log.d(TAG, "begin of save ....");
        account.display_name = accountDisplayName.getText().trim();

        //String[] serverParts = accountServer.getText().split(":");
        //         String serverDomain = SipManager.SERVER_DOMAIN;
        String serverDomain = accountServer.getText().toString();
        //account.acc_id = "<sip:" + SipUri.encodeUser(accountUserName.getText().trim()) + "@"+serverParts[0].trim()+">";
        account.acc_id = "<sip:" + SipUri.encodeUser(accountUserName.getText().trim()) + "@" + serverDomain + ">";

        //String regUri = "sip:" + accountServer.getText();
        String regUri = "sip:" + serverDomain;
        account.reg_uri = regUri;
        account.proxies = new String[] { regUri };

        account.realm = "*";
        account.username = getText(accountUserName).trim();
        account.data = getText(accountPassword);
        account.scheme = SipProfile.CRED_SCHEME_DIGEST;
        account.datatype = SipProfile.CRED_DATA_PLAIN_PASSWD;
        //By default auto transport
        account.transport = SipProfile.TRANSPORT_UDP;
        return account;
    }

    @Override
    public int getBasePreferenceResource() {
        return R.xml.w_basic_preferences;
    }

    @Override
    public boolean needRestart() {
        return false;
    }

    /**
     * Class to download the account details for the user from the NewCell server
     * @author jerredmoss
     *
     */
    public class AccountDownloader extends AsyncTask<String, Integer, HttpResponse> {

        private static final int TIMEOUT = 20000;
        private static final String TAG = "AccountDownloader";

        private DefaultHttpClient httpClient;
        private HttpParams httpParams;
        private HttpPost httpPostRequest;
        private HttpEntity response;

        private JSONObject jsonObject;
        private TelephonyManager telephonyManager;

        private String mode;

        public AccountDownloader() {

        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();

            dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
            dialog = ProgressDialog.show(parent, "Syncing", "Downloading account details...");
        }

        @Override
        protected HttpResponse doInBackground(String... params) {

            mode = params[0];

            if (SipManager.API_USER_INFO == null || SipManager.API_USER_INFO == ""
                    || SipManager.API_REQUEST_AUTH == null || SipManager.API_REQUEST_AUTH == "") {
                Log.e(TAG, "Could not retrieve API URL");
                return null;
            }

            jsonObject = new JSONObject();

            httpParams = new BasicHttpParams();
            HttpConnectionParams.setConnectionTimeout(httpParams, TIMEOUT);

            httpClient = new DefaultHttpClient(httpParams);

            telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);

            String myHexDeviceId = telephonyManager.getDeviceId();

            Log.i(TAG, "Original Device ID::" + myHexDeviceId);

            String myDeviceId = myHexDeviceId;
            int phoneType = telephonyManager.getPhoneType();

            Log.i(TAG, "Phone type::" + phoneType);

            if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) {
                // CDMA uses an 18 character MEID-DEC
                // Derived from the MEID-HEX

                myDeviceId = getMeidDecimalFromHex(myHexDeviceId);
                Log.i(TAG, "Got MEID-DEC for CDMA::" + myDeviceId);

            } else if (phoneType == TelephonyManager.PHONE_TYPE_GSM) {
                // GSM uses a 15 character IMEI
                // No need to convert

                myDeviceId = myHexDeviceId;
                Log.i(TAG, "Using IMEI for GSM::" + myDeviceId);
            } else {
                Log.e(TAG, "Different phone type::" + phoneType);
            }

            //            String myAuthKey = "";
            //            String myAuthPass = "";
            //            String concatHashes = "";

            if (mode == REQUEST_AUTH) {
                // First step, request AuthKey and AuthPass by passing ESN

                httpPostRequest = new HttpPost(SipManager.API_REQUEST_AUTH);

                try {
                    jsonObject.put(context.getString(R.string.json_esn), myDeviceId);
                } catch (JSONException e) {
                    Log.e(TAG, "Error adding esn to JSON");
                    e.printStackTrace();
                }

            } else if (mode == REQUEST_INFO) {
                // Second step, request user info by passing ESN

                httpPostRequest = new HttpPost(SipManager.API_USER_INFO);

                //               myAuthKey = sharedPref.getString(context.getString(R.string.preference_auth_key), "");
                //               myAuthPass = sharedPref.getString(context.getString(R.string.preference_auth_pass), "");

                //               Log.i(TAG, "AuthKey from preferences::" + myAuthKey);
                //               Log.i(TAG, "AuthPass from preferences::" + myAuthPass);

                try {
                    jsonObject.put(context.getString(R.string.json_esn), myDeviceId);
                    //                  jsonObject.put(context.getString(R.string.json_auth_key), myAuthKey);
                    //                  jsonObject.put(context.getString(R.string.json_auth_pass), myAuthPass);
                } catch (JSONException e) {
                    Log.e(TAG, "Error adding esn/authkey/authpass to JSON");
                    e.printStackTrace();
                }
            } else if (mode == REQUEST_COMPLETE) {
                // Third step, received user info. 
                // TODO:: Might not need

            }
            try {
                Log.i(TAG, "JSON Sending::\n" + jsonObject.toString(2));

                StringEntity se;
                se = new StringEntity(jsonObject.toString());

                httpPostRequest.setEntity(se);

                return httpClient.execute(httpPostRequest);

            } catch (UnsupportedEncodingException e) {
                Log.e(TAG, "Error downloading account details");
                Log.e(TAG, e.toString());
                e.printStackTrace();
            } catch (ClientProtocolException e) {
                Log.e(TAG, "Error downloading account details");
                Log.e(TAG, e.toString());
                e.printStackTrace();
            } catch (IOException e) {
                Log.e(TAG, "Error downloading account details");
                Log.e(TAG, e.toString());
                e.printStackTrace();
            } catch (JSONException e) {
                Log.e(TAG, "Error downloading account details");
                Log.e(TAG, e.toString());
                e.printStackTrace();
            }

            // Return null if there was an error
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);

            dialog.setProgress(values[0]);
        }

        @Override
        protected void onPostExecute(HttpResponse result) {
            super.onPostExecute(result);

            if (result == null) {
                Log.i(TAG, "Received NULL from server");

                accountDisplayName.setText(DEF_DISPLAY_NAME);
                accountUserName.setText(DEF_USER_NAME);
                accountPassword.setText(DEF_PASSWORD);
            } else {

                response = result.getEntity();

                try {
                    if (response != null) {
                        InputStream inputStream = response.getContent();

                        String resultString = convertStreamToString(inputStream);
                        inputStream.close();

                        Log.i(TAG, "String Received::\n" + resultString);

                        JSONObject jsonObjectRecv = new JSONObject(resultString);

                        Log.i(TAG, "JSONObject Received::\n " + jsonObjectRecv.toString(2));

                        if (mode == REQUEST_AUTH) {
                            // First step, received authkey and authpass, now request user info
                            updateSharedPrefs(jsonObjectRecv);

                            new AccountDownloader().execute(REQUEST_INFO);

                        } else if (mode == REQUEST_INFO) {
                            // Second step, received user info, update account details
                            updateAccountDetails(jsonObjectRecv);

                        } else if (mode == REQUEST_COMPLETE) {
                            // TODO:: Might not need
                        }

                    } else {
                        Log.e(TAG, "Received NULL from the server");
                    }
                } catch (IOException e) {
                    Log.e(TAG, "Error getting data from server");
                    Log.e(TAG, e.toString());
                    e.printStackTrace();
                } catch (JSONException e) {
                    Log.e(TAG, "Error converting response to JSON");
                    Log.e(TAG, e.toString());
                    e.printStackTrace();
                }
            }

            dialog.dismiss();
        }

    }

    /**
     * Converts a Hex MEID to a Decimal MEID
     * @param hex The hex version of the MEID
     * @return The Decimal version of the MEID
     */
    private static String getMeidDecimalFromHex(String hex) {
        /*
         * How to do it:
         * 1. Convert first 8 numbers from Hex, store in dec1
         * 2. Convert last 6 numbers from Hex, store in dec2
         * 3. If length of dec1 + dec2 == 18
         *        Decimal = dec1 + dec2
         *    ElseIf length of dec1 + dec2 < 18
         *        Decimal = dec1 + "0" + dec2
         *        Add as many 0s needed to get to 18 characters
         *
         * Example:
         *     MEID-Hex: 45685023     858729
         *     MEID-Dec: 1164464163 0 8750889
         *     or
         *     MEID-Dec: 1164464163 87508896
         */

        String hex1 = hex.substring(0, 8);
        String hex2 = hex.substring(8, hex.length());

        String dec1 = String.valueOf(Long.parseLong(hex1, 16));
        String dec2 = String.valueOf(Long.parseLong(hex2, 16));

        int length = dec1.length() + dec2.length();

        Log.i(TAG, " Dec1::" + dec1 + "\n Dec2::" + dec2 + "\n Length::" + length);

        StringBuilder decimal = new StringBuilder("");

        if (length == 18) {
            decimal.append(dec1);
            decimal.append(dec2);
        } else if (length < 18) {
            decimal.append(dec1);
            for (int i = length; i < MEID_DECIMAL_NEEDED_LENGTH; i++) {
                decimal.append("0");
            }
            decimal.append(dec2);
        } else {
            Log.e(TAG, "MEID-DEC length is not <= " + MEID_DECIMAL_NEEDED_LENGTH + ". Length = " + length);
        }

        if (decimal.length() != MEID_DECIMAL_NEEDED_LENGTH) {
            Log.e(TAG, "Decimal length != " + MEID_DECIMAL_NEEDED_LENGTH + ". " + decimal.length());
        }
        Log.i(TAG, " Decimal::" + decimal);

        return decimal.toString();
    }

    /**
     * Converts an InputStream to a String
     * @param is The InputStream to convert
     * @return The converted String
     */
    private static String convertStreamToString(InputStream is) {

        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();

        String line = null;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return sb.toString();
    }

    /**
     * Updates the users account settings for them from the account details
     * pulled from the server
     * @param account The JSON Object of the account received
     */
    private void updateAccountDetails(JSONObject account) {

        String mAccountName = "";
        String mUser = "";
        String mPassword = "";

        try {
            if (account.getString(context.getString(R.string.json_esn)).equals("")
                    || account.getString(context.getString(R.string.json_sip_username)).equals("")
                    || account.getString(context.getString(R.string.json_sip_password)).equals("")) {
                Log.i(TAG, "No account was found that matched this phone");

                accountDisplayName.setText(DEF_DISPLAY_NAME);
                accountUserName.setText(DEF_USER_NAME);
                accountPassword.setText(DEF_PASSWORD);

                /**
                 * TODO::
                 * Change the text here to be a R.string.fdasflkdjfa for language support
                 */
                Toast.makeText(parent, "No account was found that matched this phone", Toast.LENGTH_LONG).show();
                return;
            }
        } catch (JSONException e) {
            /**
             * TODO::
             * Change the text here to be a R.string.fsgkjgdfgh for language support
             */
            Toast.makeText(context, "Error downloading account details", Toast.LENGTH_LONG).show();
            Log.e(TAG, "Could not get JSON values, none found");
            e.printStackTrace();
            return;
        }

        try {
            mAccountName = account.getString(context.getString(R.string.json_mobile_number));
        } catch (JSONException e) {
            Log.e(TAG, "Could not get mobile_number, none found");
            mAccountName = DEF_DISPLAY_NAME;
            e.printStackTrace();
        }
        try {
            mUser = account.getString(context.getString(R.string.json_sip_username));
        } catch (JSONException e) {
            Log.e(TAG, "Could not get sip_username, none found");
            mUser = DEF_USER_NAME;
            e.printStackTrace();
        }
        try {
            mPassword = account.getString(context.getString(R.string.json_sip_password));
        } catch (JSONException e) {
            Log.e(TAG, "Could not get sip_password, none found");
            mPassword = DEF_PASSWORD;
            e.printStackTrace();
        }

        if (mAccountName.equals(null) || mAccountName.equals("")) {
            mAccountName = mUser;
        }

        accountDisplayName.setText(mAccountName);
        accountUserName.setText(mUser);
        accountPassword.setText(mPassword);
    }

    /**
     * Updates the shared preferences for the app for future use
     * @param result The JSON object we received with the AuthKey and AuthPass
     */
    private void updateSharedPrefs(JSONObject result) {
        String authkey = "";
        String authpass = "";

        try {
            if (result.getString(context.getString(R.string.json_auth_key)) == null
                    || result.getString(context.getString(R.string.json_auth_key)) == ""
                    || result.getString(context.getString(R.string.json_auth_pass)) == null
                    || result.getString(context.getString(R.string.json_auth_pass)) == "") {
                Log.i(TAG, "No authentication credentials were found for this account");
                /*
                 * TODO::
                 * Change the text here to be a R.string.fsgkjgdfgh for language support
                 */
                Toast.makeText(context, "No authentication credentials were returned for this account",
                        Toast.LENGTH_LONG).show();
                return;
            }

        } catch (JSONException e) {
            /*
             * TODO::
             * Change the text here to be a R.string.fsgkjgdfgh for language support
             */
            Toast.makeText(context, "Error updating authentication credentials", Toast.LENGTH_SHORT).show();
            Log.e(TAG, "Could not get JSON values from auth_request, none found");
            e.printStackTrace();
            return;
        }

        try {
            authkey = result.getString(context.getString(R.string.json_auth_key));
        } catch (JSONException e) {
            Log.e(TAG, "Could not get AuthKey, none found");
            e.printStackTrace();
            return;
        }
        try {
            authpass = result.getString(context.getString(R.string.json_auth_pass));
        } catch (JSONException e) {
            Log.e(TAG, "Could not get AuthPass, none found");
            e.printStackTrace();
            return;
        }

        // Open shared preferences for the app to retrieve AuthKey and AuthPass
        //         sharedPref = context.getSharedPreferences(
        //               context.getString(R.string.preference_file_key), 
        //               Context.MODE_PRIVATE);

        //         prefEditor = sharedPref.edit();
        prefEditor.putString(context.getString(R.string.preference_auth_key), authkey);
        prefEditor.putString(context.getString(R.string.preference_auth_pass), authpass);

        prefEditor.commit();

        Log.i(TAG, "Stored to preferences:\n    AuthKey::" + authkey + "\n    AuthPass::" + authpass);
    }

    /**
     * Create an MD5 hash from a string
     * @param str The original string
     * @return The MD5 hash of the string
     */
    private String createMD5Hash(String str) {
        final String MD5 = "MD5";
        try {
            MessageDigest digest = java.security.MessageDigest.getInstance(MD5);
            digest.update(str.getBytes());
            byte messageDigest[] = digest.digest();
            // Create hex string
            StringBuilder hexString = new StringBuilder();
            for (byte aMessageDigest : messageDigest) {
                String h = Integer.toHexString(0xFF & aMessageDigest);
                while (h.length() < 2)
                    h = "0" + h;
                hexString.append(h);
            }
            return hexString.toString();
        } catch (NoSuchAlgorithmException e) {
            Log.e(TAG, "Error in createMD5Hash()");
            Log.e(TAG, e.toString());
        }
        return null;
    }

}