Java tutorial
/* * Copyright (c) 2012 Google Inc. * * 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.github.socialc0de.gsw.android; import android.accounts.AccountManager; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.net.Uri; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.support.v7.widget.Toolbar; import android.text.Spannable; import android.text.SpannableString; import android.util.Log; import android.view.View; import android.widget.Toast; import com.appspot.donate_backend.donate.Donate; import com.appspot.donate_backend.donate.Donate.Builder; import com.appspot.donate_backend.donate.DonateScopes; import com.appspot.donate_backend.donate.model.*; import com.github.socialc0de.gsw.android.fragments.*; import com.github.socialc0de.gsw.android.tools.CloudEndpointBuilderHelper; import com.github.socialc0de.gsw.android.tools.TinyDB; import com.google.android.gms.common.GooglePlayServicesUtil; import com.google.api.client.extensions.android.http.AndroidHttp; import com.google.api.client.extensions.android.json.AndroidJsonFactory; import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential; import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException; import com.google.api.client.json.JsonFactory; import com.mikepenz.materialdrawer.AccountHeader; import com.mikepenz.materialdrawer.AccountHeaderBuilder; import com.mikepenz.materialdrawer.Drawer; import com.mikepenz.materialdrawer.DrawerBuilder; import com.mikepenz.materialdrawer.model.PrimaryDrawerItem; import com.mikepenz.materialdrawer.model.ProfileDrawerItem; import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem; import com.mikepenz.materialdrawer.model.interfaces.IProfile; import com.paypal.android.sdk.payments.*; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; import java.util.*; /** * Activity that allows the user to select the account they want to use to sign in. The class also * implements integration with Google Play Services and Google Accounts. */ public class MainActivity extends FragmentActivity { // constants for startActivityForResult flow public static final int REQUEST_ACCOUNT_PICKER = 1; static final boolean SIGN_IN_REQUIRED = false; static final int REQUEST_GOOGLE_PLAY_SERVICES = 2; static final int REQUEST_AUTHORIZATION = 3; final static String TAG = "Donate"; private static final String AUDIENCE = "server:client_id:760560844994-04u6qkvpf481an26cnhkaauaf2dvjfk0.apps.googleusercontent.com"; private static final String ACCOUNT_NAME_SETTING_NAME = "accountName"; static GoogleAccountCredential credential; private static MainActivity mainActivity; final ArrayList<Fragment> mFragments = new ArrayList<Fragment>(); public HashMap<String, Category> categories = new HashMap<String, Category>(); public String gplus_url; public TinyDB mTinyDB; Drawer mDrawer; AccountHeader headerResult; private static final String CONFIG_ENVIRONMENT = PayPalConfiguration.ENVIRONMENT_NO_NETWORK; // note that these credentials will differ between live & sandbox environments. private static final String CONFIG_CLIENT_ID = "AU-NITuyj3r7aurS3OVX-ldVgO3f7m76C1G2VR9lQxvJ_3dS4qfj7X5hyvxAtLfbJOlzu4waEf2XEHSt"; private static final int REQUEST_CODE_FUTURE_PAYMENT = 2; private static final int REQUEST_CODE_PAYMENT = 1; private static final int REQUEST_CODE_PROFILE_SHARING = 3; private static PayPalConfiguration paypalConfig = new PayPalConfiguration().environment(CONFIG_ENVIRONMENT) .clientId(CONFIG_CLIENT_ID) // The following are only used in PayPalFuturePaymentActivity. .merchantName("Example Merchant").merchantPrivacyPolicyUri(Uri.parse("https://www.example.com/privacy")) .merchantUserAgreementUri(Uri.parse("https://www.example.com/legal")); /** * Called to sign out the user, so user can later on select a different account. * * @param activity activity that initiated the sign out. */ static void onSignOut(Activity activity) { SharedPreferences settings = activity.getSharedPreferences("reguees", 0); SharedPreferences.Editor editor = settings.edit(); editor.putString(ACCOUNT_NAME_SETTING_NAME, ""); editor.commit(); credential.setSelectedAccountName(""); Intent intent = new Intent(activity, MainActivity.class); activity.startActivity(intent); } public static Map<String, Object> jsonToMap(JSONObject json) throws JSONException { Map<String, Object> retMap = new HashMap<String, Object>(); if (json != JSONObject.NULL) { retMap = toMap(json); } return retMap; } public static Map<String, Object> toMap(JSONObject object) throws JSONException { Map<String, Object> map = new HashMap<String, Object>(); Iterator<String> keysItr = object.keys(); while (keysItr.hasNext()) { String key = keysItr.next(); Object value = object.get(key); if (value instanceof JSONArray) { value = toList((JSONArray) value); } else if (value instanceof JSONObject) { value = toMap((JSONObject) value); } map.put(key, value); } return map; } public static List<Object> toList(JSONArray array) throws JSONException { List<Object> list = new ArrayList<Object>(); for (int i = 0; i < array.length(); i++) { Object value = array.get(i); if (value instanceof JSONArray) { value = toList((JSONArray) value); } else if (value instanceof JSONObject) { value = toMap((JSONObject) value); } list.add(value); } return list; } public static MainActivity getMainActivity() { return MainActivity.mainActivity; } public static GoogleAccountCredential getCredential() { return credential; } public static void setCredential(GoogleAccountCredential credential) { MainActivity.credential = credential; } /** * Initializes the activity content and then navigates to the MainActivity if the user is already * signed in or if the app is configured to not require the sign in. Otherwise it initiates * starting the UI for the account selection and a check for Google Play Services being up to * date. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new DrawerBuilder().withActivity(this).build(); if (!checkGooglePlayServicesAvailable()) { // Google Play Services are required, so don't proceed until they are installed. return; } if (isSignedIn()) { startMainActivity(); } else { startActivityForResult(credential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER); } MainActivity.mainActivity = this; Intent intent = new Intent(this, PayPalService.class); intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, paypalConfig); startService(intent); } @Override public void onDestroy() { stopService(new Intent(this, PayPalService.class)); super.onDestroy(); } private void fillLayout() { SpannableString s = new SpannableString(getString(R.string.app_name)); s.setSpan(new com.github.socialc0de.gsw.android.TypefaceSpan(getApplicationContext(), "fabiolo.otf"), 0, s.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); ((Toolbar) findViewById(R.id.app_bar)).setTitle(s); mTinyDB = new TinyDB(this); loadCategories(); loadAccount(); if (mDrawer != null && mFragments != null) { for (int i = 0; i < mFragments.size(); i++) { mDrawer.removeItem(i); } } //create the drawer and remember the `Drawer` result object headerResult = new AccountHeaderBuilder().withActivity(this).withHeaderBackground(R.drawable.productback) .withOnAccountHeaderListener(new AccountHeader.OnAccountHeaderListener() { @Override public boolean onProfileChanged(View view, IProfile profile, boolean currentProfile) { return false; } }).withSelectionListEnabledForSingleProfile(false).build(); mFragments.clear(); mFragments.add(new LocalFragment(this)); mFragments.add(new CategoryFragment(this)); mFragments.add(new ProfileFragment()); mFragments.add(new PhraseFragment()); mFragments.add(new FAQFragment()); mFragments.add(new AuthorityMapFragment()); mFragments.add(new DonateFragment()); mFragments.add(new AboutFragment()); if (mDrawer == null) { mDrawer = new DrawerBuilder().withActivity(this).withToolbar((Toolbar) findViewById(R.id.app_bar)) .withActionBarDrawerToggle(true).withAccountHeader(headerResult) .addDrawerItems( new PrimaryDrawerItem().withName(R.string.sharing_local) .withIcon(R.drawable.ic_place_black_36dp), new PrimaryDrawerItem().withName(R.string.sharing_categories) .withIcon(R.drawable.ic_view_day_black_36dp), new PrimaryDrawerItem().withName(R.string.profile) .withIcon(R.drawable.ic_assignment_ind_black_36dp), new PrimaryDrawerItem().withName(R.string.phrasebook) .withIcon(R.drawable.ic_translate_black_36dp), new PrimaryDrawerItem().withName(R.string.faq) .withIcon(R.drawable.ic_question_answer_black_36dp), new PrimaryDrawerItem().withName(R.string.authority_map) .withIcon(R.drawable.ic_map_black_36dp), new PrimaryDrawerItem().withName(R.string.donate) .withIcon(R.drawable.ic_attach_money_black_36dp), new PrimaryDrawerItem().withName(R.string.about) .withIcon(R.drawable.ic_info_black_36dp)) .withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() { @Override public boolean onItemClick(View view, int position, IDrawerItem drawerItem) { // do something with the clicked item :D if (getSupportFragmentManager().findFragmentByTag( mFragments.get(position - 1).getClass().getSimpleName()) != null) return false; getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); getSupportFragmentManager().beginTransaction() .replace(R.id.container, mFragments.get(position - 1), mFragments.get(position - 1).getClass().getSimpleName()) .addToBackStack(null).commit(); // closes Drawer return false; } }).build(); } getSupportFragmentManager().beginTransaction().replace(R.id.container, mFragments.get(0)).commit(); } /** * Handles the results from activities launched to select an account and to install Google Play * Services. */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case REQUEST_ACCOUNT_PICKER: if (data != null && data.getExtras() != null) { String accountName = data.getExtras().getString(AccountManager.KEY_ACCOUNT_NAME); if (accountName != null) { onSignedIn(accountName); } } else if (!SIGN_IN_REQUIRED) { AlertDialog.Builder alert = new AlertDialog.Builder(this); alert.setTitle(R.string.are_you_sure); alert.setMessage(R.string.not_all_features); alert.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { startMainActivity(); } }); alert.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { startActivityForResult(credential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER); } }); alert.show(); } break; case REQUEST_GOOGLE_PLAY_SERVICES: if (resultCode != Activity.RESULT_OK) { checkGooglePlayServicesAvailable(); } break; } if (requestCode == REQUEST_CODE_PAYMENT) { if (resultCode == Activity.RESULT_OK) { PaymentConfirmation confirm = data.getParcelableExtra(PaymentActivity.EXTRA_RESULT_CONFIRMATION); if (confirm != null) { try { Log.i(TAG, confirm.toJSONObject().toString(4)); Log.i(TAG, confirm.getPayment().toJSONObject().toString(4)); /** * TODO: send 'confirm' (and possibly confirm.getPayment() to your server for verification * or consent completion. * See https://developer.paypal.com/webapps/developer/docs/integration/mobile/verify-mobile-payment/ * for more details. * * For sample mobile backend interactions, see * https://github.com/paypal/rest-api-sdk-python/tree/master/samples/mobile_backend */ Toast.makeText(getApplicationContext(), "PaymentConfirmation info received from PayPal", Toast.LENGTH_LONG).show(); } catch (JSONException e) { Log.e(TAG, "an extremely unlikely failure occurred: ", e); } } } else if (resultCode == Activity.RESULT_CANCELED) { Log.i(TAG, "The user canceled."); } else if (resultCode == PaymentActivity.RESULT_EXTRAS_INVALID) { Log.i(TAG, "An invalid Payment or PayPalConfiguration was submitted. Please see the docs."); } } else if (requestCode == REQUEST_CODE_FUTURE_PAYMENT) { if (resultCode == Activity.RESULT_OK) { PayPalAuthorization auth = data .getParcelableExtra(PayPalFuturePaymentActivity.EXTRA_RESULT_AUTHORIZATION); if (auth != null) { try { Log.i("FuturePaymentExample", auth.toJSONObject().toString(4)); String authorization_code = auth.getAuthorizationCode(); Log.i("FuturePaymentExample", authorization_code); Toast.makeText(getApplicationContext(), "Future Payment code received from PayPal", Toast.LENGTH_LONG).show(); } catch (JSONException e) { Log.e("FuturePaymentExample", "an extremely unlikely failure occurred: ", e); } } } else if (resultCode == Activity.RESULT_CANCELED) { Log.i("FuturePaymentExample", "The user canceled."); } else if (resultCode == PayPalFuturePaymentActivity.RESULT_EXTRAS_INVALID) { Log.i("FuturePaymentExample", "Probably the attempt to previously start the PayPalService had an invalid PayPalConfiguration. Please see the docs."); } } else if (requestCode == REQUEST_CODE_PROFILE_SHARING) { if (resultCode == Activity.RESULT_OK) { PayPalAuthorization auth = data .getParcelableExtra(PayPalProfileSharingActivity.EXTRA_RESULT_AUTHORIZATION); if (auth != null) { try { Log.i("ProfileSharingExample", auth.toJSONObject().toString(4)); String authorization_code = auth.getAuthorizationCode(); Log.i("ProfileSharingExample", authorization_code); Toast.makeText(getApplicationContext(), "Profile Sharing code received from PayPal", Toast.LENGTH_LONG).show(); } catch (JSONException e) { Log.e("ProfileSharingExample", "an extremely unlikely failure occurred: ", e); } } } else if (resultCode == Activity.RESULT_CANCELED) { Log.i("ProfileSharingExample", "The user canceled."); } else if (resultCode == PayPalFuturePaymentActivity.RESULT_EXTRAS_INVALID) { Log.i("ProfileSharingExample", "Probably the attempt to previously start the PayPalService had an invalid PayPalConfiguration. Please see the docs."); } } } /** * Retrieves the previously used account name from the application preferences and checks if the * credential object can be set to this account. */ private boolean isSignedIn() { credential = GoogleAccountCredential.usingOAuth2(this, Collections.singleton(DonateScopes.USERINFO_EMAIL + " " + DonateScopes.PLUS_LOGIN)); SharedPreferences settings = getSharedPreferences("refugees", 0); String accountName = settings.getString(ACCOUNT_NAME_SETTING_NAME, null); credential.setSelectedAccountName(accountName); return credential.getSelectedAccount() != null; } /** * Called when the user selected an account. The account name is stored in the application * preferences and set in the credential object. * * @param accountName the account that the user selected. */ private void onSignedIn(String accountName) { SharedPreferences settings = getSharedPreferences("refugees", 0); Log.d("GSW MainActivity", accountName); SharedPreferences.Editor editor = settings.edit(); editor.putString(ACCOUNT_NAME_SETTING_NAME, accountName); editor.commit(); credential.setSelectedAccountName(accountName); Runnable runnable = new Runnable() { @Override public void run() { Builder endpointBuilder = new Donate.Builder(AndroidHttp.newCompatibleTransport(), new AndroidJsonFactory(), CloudEndpointBuilderHelper.getRequestInitializer()); Donate service = CloudEndpointBuilderHelper.updateBuilder(endpointBuilder).build(); try { final User result = service.user().create(new UserProto()).execute(); Log.d("GSW MainActivity", result.toString()); runOnUiThread(new Runnable() { public void run() { startMainActivity(); } }); } catch (UserRecoverableAuthIOException e) { Log.d("GSW MainActivity", "e", e); final UserRecoverableAuthIOException e2 = e; runOnUiThread(new Runnable() { public void run() { startActivityForResult(e2.getIntent(), 2); } }); } catch (IOException e) { Log.d("GSW MainActivity", "e", e); } } }; new Thread(runnable).start(); } /** * Navigates to the MainActivity */ private void startMainActivity() { fillLayout(); } /** * Checks if Google Play Services are installed and if not it initializes opening the dialog to * allow user to install Google Play Services. */ private boolean checkGooglePlayServicesAvailable() { final int connectionStatusCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this); if (GooglePlayServicesUtil.isUserRecoverableError(connectionStatusCode)) { showGooglePlayServicesAvailabilityErrorDialog(connectionStatusCode); return false; } return true; } /** * Shows the Google Play Services dialog on UI thread. */ void showGooglePlayServicesAvailabilityErrorDialog(final int connectionStatusCode) { runOnUiThread(new Runnable() { @Override public void run() { Dialog dialog = GooglePlayServicesUtil.getErrorDialog(connectionStatusCode, MainActivity.this, REQUEST_GOOGLE_PLAY_SERVICES); dialog.show(); } }); } public HashMap<String, Category> parseCat(String json) { try { JSONObject cat_json = new JSONObject(json); HashMap<String, Category> map = new HashMap<String, Category>(); Iterator<String> keysItr = cat_json.keys(); while (keysItr.hasNext()) { String key = keysItr.next(); Object value = cat_json.get(key); Category cat = new Category(); if (value instanceof JSONObject) { JsonFactory factory = new AndroidJsonFactory(); cat = factory.fromString(value.toString(), Category.class); } map.put(key, cat); } return map; } catch (Exception e) { Log.d(TAG, "Error", e); return null; } } public void loadCategories() { if (mTinyDB.getString("categories") != "") { categories = parseCat(mTinyDB.getString("categories")); Log.d(TAG, mTinyDB.getString("categories")); } Runnable runnable = new Runnable() { @Override public void run() { Builder endpointBuilder = new Donate.Builder(AndroidHttp.newCompatibleTransport(), new AndroidJsonFactory(), CloudEndpointBuilderHelper.getRequestInitializer()); Donate service = CloudEndpointBuilderHelper.updateBuilder(endpointBuilder).build(); CategoryCollection result; try { result = service.cat().list().execute(); Log.d("GSW MainActivity", result.toString()); if (result.getItems() != null) { for (Category cat : result.getItems()) { categories.put(cat.getId(), cat); } } mTinyDB.putString("categories", new JSONObject(categories).toString()); } catch (UserRecoverableAuthIOException e) { final UserRecoverableAuthIOException e2 = e; runOnUiThread(new Runnable() { public void run() { startActivityForResult(e2.getIntent(), 2); } }); Log.d("GSW MainActivity", "e", e); } catch (Exception e) { Log.d("GSW MainActivity", "e", e); } } }; new Thread(runnable).start(); } public void loadAccount() { if (credential.getSelectedAccount() != null) { gplus_url = mTinyDB.getString("gplus_url"); Runnable runnable = new Runnable() { @Override public void run() { Builder endpointBuilder = new Donate.Builder(AndroidHttp.newCompatibleTransport(), new AndroidJsonFactory(), CloudEndpointBuilderHelper.getRequestInitializer()); Donate service = CloudEndpointBuilderHelper.updateBuilder(endpointBuilder).build(); try { final UserProtoImAddressNameImageUrl result = service.user().data().execute(); runOnUiThread(new Runnable() { public void run() { if (result.getImageUrl() != null) { headerResult.addProfiles(new ProfileDrawerItem().withName(result.getName()) .withEmail(credential.getSelectedAccountName()) .withIcon(result.getImageUrl())); } else { headerResult.addProfiles(new ProfileDrawerItem().withName(result.getName()) .withEmail(credential.getSelectedAccountName())); } } }); Log.d("GSW MainActivity", result.toString()); Map<String, Object> im = jsonToMap(new JSONObject(result.getIm().toString())); gplus_url = (String) ((HashMap) im.get("gplus")).get("url"); mTinyDB.putString("gplus_url", gplus_url); } catch (UserRecoverableAuthIOException e) { final UserRecoverableAuthIOException e2 = e; runOnUiThread(new Runnable() { public void run() { startActivityForResult(e2.getIntent(), 2); } }); Log.d("GSW MainActivity", "e", e); } catch (Exception e) { Log.d("GSW MainActivity", "e", e); } } }; new Thread(runnable).start(); } else { gplus_url = ""; mTinyDB.putString("gplus_url", gplus_url); } } public Drawer getmDrawer() { return mDrawer; } public void setmDrawer(Drawer mDrawer) { this.mDrawer = mDrawer; } public static PayPalConfiguration getPaypalConfig() { return paypalConfig; } public static void setPaypalConfig(PayPalConfiguration paypalConfig) { MainActivity.paypalConfig = paypalConfig; } }