Java tutorial
/* * Copyright 2016 Mobicage NV * * 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. * * @@license_version:1.1@@ */ package com.mobicage.rogerthat; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import org.json.simple.JSONValue; import android.Manifest; import android.app.AlertDialog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.net.Uri.Builder; import android.os.Bundle; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.view.GestureDetector; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.EditorInfo; import android.widget.AlphabetIndexer; import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.CursorAdapter; import android.widget.ImageView; import android.widget.ListView; import android.widget.SectionIndexer; import android.widget.TextView; import android.widget.TextView.OnEditorActionListener; import android.widget.ViewFlipper; import com.facebook.FacebookException; import com.facebook.Session; import com.facebook.SessionState; import com.facebook.UiLifecycleHelper; import com.facebook.widget.FacebookDialog; import com.facebook.widget.WebDialog; import com.mobicage.rogerth.at.R; import com.mobicage.rogerthat.config.Configuration; import com.mobicage.rogerthat.plugins.friends.Contact; import com.mobicage.rogerthat.plugins.friends.FriendsPlugin; import com.mobicage.rogerthat.plugins.friends.PhoneContacts; import com.mobicage.rogerthat.plugins.scan.ScanTabActivity; import com.mobicage.rogerthat.util.FacebookUtils; import com.mobicage.rogerthat.util.FacebookUtils.PermissionType; import com.mobicage.rogerthat.util.RegexPatterns; import com.mobicage.rogerthat.util.logging.L; import com.mobicage.rogerthat.util.sms.SMSManager; import com.mobicage.rogerthat.util.system.SafeAsyncTask; import com.mobicage.rogerthat.util.system.SafeBroadcastReceiver; import com.mobicage.rogerthat.util.system.SafeDialogInterfaceOnClickListener; import com.mobicage.rogerthat.util.system.SafeRunnable; import com.mobicage.rogerthat.util.system.SafeViewOnClickListener; import com.mobicage.rogerthat.util.system.SystemUtils; import com.mobicage.rogerthat.util.system.T; import com.mobicage.rogerthat.util.ui.ImageHelper; import com.mobicage.rogerthat.util.ui.SeparatedListAdapter; import com.mobicage.rogerthat.util.ui.Slider; import com.mobicage.rogerthat.util.ui.Slider.Swiper; import com.mobicage.rogerthat.util.ui.UIUtils; import com.mobicage.rpc.IncompleteMessageException; import com.mobicage.rpc.config.AppConstants; import com.mobicage.rpc.config.CloudConstants; import com.mobicage.to.friends.FacebookRogerthatProfileMatchTO; import com.mobicage.to.friends.FindRogerthatUsersViaEmailResponseTO; import com.mobicage.to.friends.FindRogerthatUsersViaFacebookResponseTO; public class AddFriendsActivity extends ServiceBoundActivity { public static final String CONFIG = "com.mobicage.rogerthat.plugins.friends.ADD_FRIENDS"; public static final String AB_RESULT = "AB_RESULT"; public static final String FB_RESULT = "FB_RESULT"; public static final String FB_POST_ON_WALL = "FB_POST_ON_WALL"; public static final String INTENT_KEY_LAUNCHINFO = "INTENT_KEY_LAUNCHINFO"; public static final String INTENT_VALUE_SHOW_CONTACTS = "SHOW_CONTACTS"; public static final String INTENT_VALUE_SHOW_FACEBOOK = "SHOW_FACEBOOK"; public static final int MY_PERMISSION_REQUEST_READ_CONTACTS = 1; private static final int TYPE_FB_MATCH = 4; private static final int TYPE_AB_MATCH = 1; private static final int TYPE_MAIL = 2; private static final int TYPE_SMS = 3; private ViewFlipper mViewFlipper; private GestureDetector mGestureScanner; private FriendsPlugin mFriendsPlugin; private PhoneContacts mPhoneContacts; private BroadcastReceiver mBroadcastReceiver; private List<String> mPendingInvites; private List<String> mCurrentInvites; private Configuration mCfg; private boolean mFbPageConfigured = false; private final Map<String, Bitmap> mFbAvatars = new HashMap<String, Bitmap>(); private UiLifecycleHelper mUiHelper; private Cursor mCursorEmail; private Cursor mPhoneCursor; private Contact mCurrentContact = null; @Override protected void onCreate(Bundle savedInstanceState) { T.UI(); super.onCreate(savedInstanceState); setContentView(R.layout.add_friends); final int btnText; switch (AppConstants.FRIENDS_CAPTION) { case COLLEAGUES: btnText = R.string.invite_colleague; break; case CONTACTS: btnText = R.string.invite_contact; break; case FRIENDS: default: btnText = R.string.invite_friend; break; } ((Button) findViewById(R.id.add_via_email_button)).setText(btnText); mViewFlipper = (ViewFlipper) findViewById(R.id.view_flipper); Swiper leftSwiper = new Swiper() { @Override public Intent onSwipe() { int i = mViewFlipper.getDisplayedChild(); if (i < mViewFlipper.getChildCount()) { displayTab(i + 1); } return null; } }; Swiper rightSwiper = new Swiper() { @Override public Intent onSwipe() { int i = mViewFlipper.getDisplayedChild(); if (i > 0) { displayTab(i - 1); } return null; } }; mGestureScanner = new GestureDetector(new Slider(this, this, leftSwiper, rightSwiper)); Intent intent = getIntent(); if (intent.hasExtra(INTENT_KEY_LAUNCHINFO)) { if (intent.getStringExtra(INTENT_KEY_LAUNCHINFO).equals(INTENT_VALUE_SHOW_CONTACTS)) { displayTab(0); } else if (intent.getStringExtra(INTENT_KEY_LAUNCHINFO).equals(INTENT_VALUE_SHOW_FACEBOOK)) { displayTab(1); } } ((TextView) findViewById(R.id.add_via_contacts_description)) .setText(getString(R.string.add_via_contacts_description, getString(R.string.app_name))); ((TextView) findViewById(R.id.add_via_facebook_description)) .setText(getString(R.string.add_via_facebook_description, getString(R.string.app_name))); mUiHelper = new UiLifecycleHelper(this, null); mUiHelper.onCreate(savedInstanceState); } @Override public boolean dispatchTouchEvent(MotionEvent e) { if (mGestureScanner != null) { mGestureScanner.onTouchEvent(e); } return super.dispatchTouchEvent(e); } @Override public void finish() { Configuration cfg = mService.getConfigurationProvider().getConfiguration(CONFIG); cfg.put(AB_RESULT, ""); cfg.put(FB_RESULT, ""); mService.getConfigurationProvider().updateConfigurationNow(CONFIG, cfg); super.finish(); } protected MyIdentity getMyIdentity() { return mService.getIdentityStore().getIdentity(); } private BroadcastReceiver getBroadcastReceiver() { T.UI(); return new SafeBroadcastReceiver() { @Override public String[] onSafeReceive(Context context, Intent intent) { T.UI(); if (FriendsPlugin.ADDRESSBOOK_SCANNED_INTENT.equals(intent.getAction())) { mCfg = mService.getConfigurationProvider().getConfiguration(CONFIG); configureContactsView(); } else if (FriendsPlugin.ADDRESSBOOK_SCAN_FAILED_INTENT.equals(intent.getAction())) { displayContactsPage(3, null); } else if (FriendsPlugin.FACEBOOK_SCANNED_INTENT.equals(intent.getAction())) { mFbPageConfigured = false; mCfg = mService.getConfigurationProvider().getConfiguration(CONFIG); configureFacebookView(); } else if (FriendsPlugin.FACEBOOK_SCAN_FAILED_INTENT.equals(intent.getAction())) { displayContactsPage(3, getString(R.string.error_find_from_facebook, getString(R.string.app_name))); } return new String[] { intent.getAction() }; // ignore intents (with this action) older than this one }; }; } @Override protected void onServiceBound() { T.UI(); mFriendsPlugin = mService.getPlugin(FriendsPlugin.class); mPhoneContacts = new PhoneContacts(getContentResolver()); mPendingInvites = mFriendsPlugin.getStore().getPendingInvitations(); mCurrentInvites = new ArrayList<String>(); mCfg = mService.getConfigurationProvider().getConfiguration(CONFIG); configureTabs(); configureContactsView(); configureFacebookView(); configureQrScanView(); configureMailView(); mBroadcastReceiver = getBroadcastReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction(FriendsPlugin.ADDRESSBOOK_SCANNED_INTENT); filter.addAction(FriendsPlugin.ADDRESSBOOK_SCAN_FAILED_INTENT); filter.addAction(FriendsPlugin.FACEBOOK_SCANNED_INTENT); filter.addAction(FriendsPlugin.FACEBOOK_SCAN_FAILED_INTENT); registerReceiver(mBroadcastReceiver, filter); setNavigationBarVisible(AppConstants.SHOW_NAV_HEADER); setNavigationBarTitle(getNavigationBarTitle()); findViewById(R.id.navigation_bar_home_button).setOnClickListener(new SafeViewOnClickListener() { @Override public void safeOnClick(View v) { Intent i = new Intent(AddFriendsActivity.this, HomeActivity.class); i.setFlags(MainActivity.FLAG_CLEAR_STACK); startActivity(i); finish(); } }); } private int getNavigationBarTitle() { switch (AppConstants.FRIENDS_CAPTION) { case COLLEAGUES: return R.string.find_colleagues; case CONTACTS: return R.string.find_contacts; case FRIENDS: default: return R.string.invite_friends_short; } } @Override protected void onResume() { super.onResume(); mUiHelper.onResume(); if (getWasPaused() && mCursorEmail != null) { startManagingCursor(mCursorEmail); } if (getWasPaused() && mPhoneCursor != null) { startManagingCursor(mPhoneCursor); } } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); mUiHelper.onSaveInstanceState(outState); } @Override public void onPause() { super.onPause(); mUiHelper.onPause(); if (mCursorEmail != null) { stopManagingCursor(mCursorEmail); } if (mPhoneCursor != null) { stopManagingCursor(mPhoneCursor); } } @Override public void onDestroy() { super.onDestroy(); mUiHelper.onDestroy(); } @Override protected void onServiceUnbound() { T.UI(); unregisterReceiver(mBroadcastReceiver); } @Override public void onConfigurationChanged(android.content.res.Configuration newConfig) { super.onConfigurationChanged(newConfig); int qrPage = 2; boolean qrPageShown = mViewFlipper.getDisplayedChild() == qrPage; mViewFlipper.removeViewAt(qrPage); mViewFlipper.addView(getLayoutInflater().inflate(R.layout.add_friends_via_qr_scan, null), qrPage); configureQrScanView(); if (qrPageShown) { mViewFlipper.setDisplayedChild(qrPage); } } private void displayTab(final int tab) { mViewFlipper.setDisplayedChild(tab); final int[] indicators = new int[] { R.id.contacts_indicator, R.id.facebook_indicator, R.id.qr_scan_indicator, R.id.mail_indicator }; for (int i = 0; i < indicators.length; i++) { findViewById(indicators[i]).setVisibility(i == tab ? View.VISIBLE : View.INVISIBLE); } } private void configureTabs() { T.UI(); final int[] views = new int[] { R.id.contacts_layout, R.id.facebook_layout, R.id.qr_scan_layout, R.id.mail_layout }; for (int v = 0; v < views.length; v++) { final int x = v; if (views[v] == R.id.facebook_layout && AppConstants.FACEBOOK_APP_ID == null) { findViewById(views[v]).setVisibility(View.GONE); continue; } findViewById(views[v]).setOnClickListener(new SafeViewOnClickListener() { @Override public void safeOnClick(View v) { if (x != mViewFlipper.getDisplayedChild()) { displayTab(x); if (views[x] == R.id.facebook_layout && !mFbPageConfigured) { configureFacebookView(); } } } }); } } private void configureContactsView() { T.UI(); String jsonResult = null; if (mCfg != null) { jsonResult = mCfg.get(AB_RESULT, ""); } if ("".equals(jsonResult)) { displayContactsPage(0, null); } else { displayContactsPage(2, jsonResult); } } private void displayContactsPage(int child, Object context) { T.UI(); SafeViewOnClickListener btnOnClickListener = new SafeViewOnClickListener() { @Override public void safeOnClick(final View v) { if (!mService.isPermitted(Manifest.permission.READ_CONTACTS)) { ActivityCompat.requestPermissions(AddFriendsActivity.this, new String[] { Manifest.permission.READ_CONTACTS }, MY_PERMISSION_REQUEST_READ_CONTACTS); return; } if (mFriendsPlugin.findRogerthatUsersViaAddressBook()) { displayContactsPage(1, null); } else { displayContactsPage(3, null); } } }; switch (child) { case 0: ((Button) findViewById(R.id.add_via_contacts_button)).setOnClickListener(btnOnClickListener); break; case 1: // Static page with only text and spinner break; case 2: displayContactsResult((String) context); break; case 3: ((Button) findViewById(R.id.add_via_contacts_try_again)).setOnClickListener(btnOnClickListener); break; default: break; } ((ViewFlipper) findViewById(R.id.add_via_contacts_view_flipper)).setDisplayedChild(child); } private void displayContactsResult(String jsonResult) { T.UI(); UIUtils.cancelNotification(this, R.integer.ab_scan_finished); @SuppressWarnings("unchecked") Map<String, Object> responseMap = (Map<String, Object>) JSONValue.parse(jsonResult); FindRogerthatUsersViaEmailResponseTO responseTO; try { responseTO = new FindRogerthatUsersViaEmailResponseTO(responseMap); } catch (IncompleteMessageException e) { L.bug(e); displayContactsPage(3, null); return; } // Get the e-mails of my Rogerthat friends List<String> rtFriendEmails = mFriendsPlugin.getStore().getEmails(); rtFriendEmails.add(getMyIdentity().getEmail()); // Get list of Contacts for the matched results List<Contact> matches = new ArrayList<Contact>(responseTO.matched_addresses.length); for (String email : responseTO.matched_addresses) { if (rtFriendEmails.contains(email)) continue; // We are already friend with the found match Cursor c = mPhoneContacts.getContactByEmail(email); if (c == null) { L.d("getContactByEmail cursor is null!"); continue; } try { if (c.moveToFirst()) { Contact contact = mPhoneContacts.fromCursor(c); matches.add(contact); } } finally { c.close(); } } // Get contact the IDs for my Rogerthat friends (they do not have to be shown in the list) List<Integer> rtFriendInContacts = new ArrayList<Integer>(); for (String email : rtFriendEmails) { Cursor c = mPhoneContacts.getContactByEmail(email); if (c == null) { L.d("getContactByEmail cursor is null!"); continue; } try { if (c.moveToFirst()) { Contact contact = mPhoneContacts.fromCursor(c); L.d("Rogerthat friend " + email + " also found in contacts"); rtFriendInContacts.add(contact.id); } } finally { c.close(); } } SeparatedListAdapter adapter = new SeparatedListAdapter(this); String resultTitle; final int l = responseTO.matched_addresses.length; if (l == 0) { resultTitle = getString(R.string.contacts_found_none, getString(R.string.app_name)); } else if (l == 1) { resultTitle = getString(R.string.contacts_found_1, getString(R.string.app_name)); } else { resultTitle = getString(R.string.contacts_found_more, l, getString(R.string.app_name)); } ContactsListAdapter matchesAdapter = new ContactsListAdapter(matches, TYPE_AB_MATCH, R.string.add, R.string.sent); adapter.addSection(resultTitle, matchesAdapter); String[] rogerthatEmails = rtFriendEmails.toArray(new String[rtFriendEmails.size()]); mCursorEmail = mPhoneContacts.getContactsPerEmail(rogerthatEmails, rtFriendInContacts); startManagingCursor(mCursorEmail); if (mCursorEmail != null && mCursorEmail.getCount() > 0) { ContactsCursorAdapter adapter2 = new ContactsCursorAdapter(mCursorEmail, TYPE_MAIL, R.string.invite, R.string.invited); final int text; switch (AppConstants.FRIENDS_CAPTION) { case COLLEAGUES: text = R.string.invite_colleagues_via_email; break; case CONTACTS: text = R.string.invite_contacts_via_email; break; case FRIENDS: default: text = R.string.invite_via_email; break; } adapter.addSection(getString(text), adapter2); } else if (mCursorEmail == null) { L.d("getContactsPerEmail cursor is null!"); } if (SystemUtils.getActionDialIntent(this) != null) { mPhoneCursor = mPhoneContacts.getContactsPerPhone(rtFriendInContacts); startManagingCursor(mPhoneCursor); if (mPhoneCursor != null && mPhoneCursor.getCount() > 0) { ContactsCursorAdapter adapter2 = new ContactsCursorAdapter(mPhoneCursor, TYPE_SMS, R.string.invite, R.string.invited); final int text; switch (AppConstants.FRIENDS_CAPTION) { case COLLEAGUES: text = R.string.invite_colleagues_via_sms; break; case CONTACTS: text = R.string.invite_contacts_via_sms; break; case FRIENDS: default: text = R.string.invite_via_sms; break; } adapter.addSection(getString(text), adapter2); } else if (mPhoneCursor == null) { L.d("getContactsPerPhone cursor is null!"); } } ListView list = (ListView) findViewById(R.id.add_via_contacts_result); list.setAdapter(adapter); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); final Session session = Session.getActiveSession(); if (session != null) { session.onActivityResult(this, requestCode, resultCode, data); } mUiHelper.onActivityResult(requestCode, resultCode, data, new FacebookDialog.Callback() { @Override public void onError(FacebookDialog.PendingCall pendingCall, Exception error, Bundle data) { findRogerthatUsersViaFacebook(); } @Override public void onComplete(FacebookDialog.PendingCall pendingCall, Bundle data) { findRogerthatUsersViaFacebook(); } }); } private void configureFacebookView() { T.UI(); if (!mFbPageConfigured) { String jsonResult = null; if (mCfg != null) { jsonResult = mCfg.get(FB_RESULT, ""); } if ("".equals(jsonResult)) { displayFacebookPage(0, null); mFbPageConfigured = true; } else if (mViewFlipper.getDisplayedChild() == 1) { displayFacebookPage(2, jsonResult); mFbPageConfigured = true; } } } private void displayFacebookErrorPage(Throwable e) { T.UI(); if (e != null) L.bug(e); displayFacebookPage(3, getString(R.string.error_load_facebook_friends)); } private void findRogerthatUsersViaFacebook() { T.UI(); if (mFriendsPlugin.findRogerthatUsersViaFacebook(Session.getActiveSession().getAccessToken())) { displayFacebookPage(1, null); } else { displayFacebookPage(3, getString(R.string.error_find_from_facebook, getString(R.string.app_name))); } } private void askToPostOnWall() { AlertDialog.Builder builder = new AlertDialog.Builder(AddFriendsActivity.this); builder.setMessage(getString(R.string.fb_ask_post_on_wall, getString(R.string.app_name))); builder.setPositiveButton(R.string.post, new SafeDialogInterfaceOnClickListener() { @Override public void safeOnClick(DialogInterface dialog, int which) { if (!mService.getNetworkConnectivityManager().isConnected()) { UIUtils.showNoNetworkDialog(AddFriendsActivity.this); return; } postOnWall(); mCfg.put(FB_POST_ON_WALL, false); mService.getConfigurationProvider().updateConfigurationNow(CONFIG, mCfg); } }); builder.setNegativeButton(R.string.cancel, new SafeDialogInterfaceOnClickListener() { @Override public void safeOnClick(DialogInterface dialog, int which) { findRogerthatUsersViaFacebook(); mCfg.put(FB_POST_ON_WALL, false); mService.getConfigurationProvider().updateConfigurationNow(CONFIG, mCfg); } }); builder.create().show(); } private void postOnWall() { FacebookUtils.ensureOpenSession(this, Arrays.asList("email", "user_friends"), PermissionType.READ, new Session.StatusCallback() { @Override public void call(Session session, SessionState state, Exception exception) { if (session != Session.getActiveSession()) { session.removeCallback(this); return; } session.removeCallback(this); if (exception == null && session.isOpened()) { String myEmailHash = new String(getMyIdentity().getEmailHash()); String picture = CloudConstants.HTTPS_BASE_URL + "/invite?code=" + myEmailHash; Uri identityUri = Uri.parse(getMyIdentity().getShortLink()); Builder b = identityUri.buildUpon(); b.appendQueryParameter("target", "fbwall"); b.appendQueryParameter("from", "phone"); b.build(); String link = b.toString(); String caption = getString(R.string.fb_wall_post_caption, getString(R.string.app_name)); String description = getString(R.string.fb_wall_post_description, getString(R.string.app_name)); L.d("Posting to facebook:\n- FACEBOOK_APP_ID: " + CloudConstants.FACEBOOK_APP_ID + "\n- Picture: " + picture + "\n- Catption: " + caption + "\n- Description: " + description + "\n- Link :" + link); if (FacebookDialog.canPresentShareDialog(getApplicationContext(), FacebookDialog.ShareDialogFeature.SHARE_DIALOG)) { L.d("Share via FacebookDialog"); FacebookDialog shareDialog = new FacebookDialog.ShareDialogBuilder( AddFriendsActivity.this).setLink(link).setPicture(picture) .setCaption(caption).setDescription(description).build(); mUiHelper.trackPendingDialogCall(shareDialog.present()); } else { L.d("Share via WebDialog"); Bundle params = new Bundle(); params.putString("app_id", CloudConstants.FACEBOOK_APP_ID); params.putString("picture", picture); params.putString("link", link); params.putString("caption", caption); params.putString("description", description); new WebDialog.FeedDialogBuilder(AddFriendsActivity.this, session, params) .setOnCompleteListener(new WebDialog.OnCompleteListener() { @Override public void onComplete(Bundle values, FacebookException error) { findRogerthatUsersViaFacebook(); } }).build().show(); } } } }, true); } private void displayFacebookPage(final int child, final Object context) { T.UI(); SafeViewOnClickListener btnOnclickListener = new SafeViewOnClickListener() { @Override public void safeOnClick(final View v) { FacebookUtils.ensureOpenSession(AddFriendsActivity.this, Arrays.asList("email", "user_friends"), PermissionType.READ, new Session.StatusCallback() { @Override public void call(Session session, SessionState state, Exception exception) { if (session != Session.getActiveSession()) { session.removeCallback(this); return; } if (exception == null && session.isOpened()) { session.removeCallback(this); if (session.getPermissions().contains("email")) { if (getMyIdentity().getShortLink() != null && mCfg.get(FB_POST_ON_WALL, true)) { askToPostOnWall(); } else { findRogerthatUsersViaFacebook(); } } } } }, true); } }; switch (child) { case 0: ((Button) findViewById(R.id.add_via_facebook_button)).setOnClickListener(btnOnclickListener); break; case 1: // Static page with only text and spinner break; case 2: displayFacebookResult((String) context); break; case 3: ((TextView) findViewById(R.id.add_via_facebook_error)).setText((String) context); ((Button) findViewById(R.id.add_via_facebook_try_again)).setOnClickListener(btnOnclickListener); break; default: break; } ((ViewFlipper) findViewById(R.id.add_via_facebook_view_flipper)).setDisplayedChild(child); } @SuppressWarnings("unchecked") private void displayFacebookResult(final String jsonResult) { T.UI(); UIUtils.cancelNotification(this, R.integer.fb_scan_finished); Map<String, Object> responseMap = (Map<String, Object>) JSONValue.parse(jsonResult); final FindRogerthatUsersViaFacebookResponseTO responseTO; try { responseTO = new FindRogerthatUsersViaFacebookResponseTO(responseMap); } catch (IncompleteMessageException e) { displayFacebookErrorPage(e); return; } final List<Contact> matches = new ArrayList<Contact>(); for (FacebookRogerthatProfileMatchTO match : responseTO.matches) { matches.add(new FacebookContact(match)); } displayFacebookResultListView(matches); } private void displayFacebookResultListView(List<Contact> matches) { T.UI(); findViewById(R.id.add_via_facebook_spinner).setVisibility(View.GONE); ListView listView = (ListView) findViewById(R.id.add_via_facebook_result); listView.setVisibility(View.VISIBLE); SeparatedListAdapter adapter = new SeparatedListAdapter(this); String resultTitle; final int l = matches.size(); if (l == 0) { resultTitle = getString(R.string.fb_friends_found_none, getString(R.string.app_name)); } else if (l == 1) { resultTitle = getString(R.string.fb_friends_found_1, getString(R.string.app_name)); } else { resultTitle = getString(R.string.fb_friends_found_more, l, getString(R.string.app_name)); } ContactsListAdapter matchesAdapter = new ContactsListAdapter(matches, TYPE_FB_MATCH, R.string.add, R.string.sent); adapter.addSection(resultTitle, matchesAdapter); listView.setAdapter(adapter); } private void configureQrScanView() { T.UI(); final Button btn = (Button) findViewById(R.id.add_via_qr_scan_button); btn.setText(getString(R.string.scan_passport, getString(R.string.app_name))); btn.setOnClickListener(new SafeViewOnClickListener() { @Override public void safeOnClick(View v) { Intent i = new Intent(AddFriendsActivity.this, ScanTabActivity.class); i.setAction(ScanTabActivity.START_SCANNER_INTENT_ACTION); startActivity(i); } }); final ImageView imgView = (ImageView) findViewById(R.id.my_qr); imgView.setImageBitmap(mService.getIdentityStore().getIdentity().getQRBitmap()); } private void configureMailView() { T.UI(); final AutoCompleteTextView emailText = (AutoCompleteTextView) findViewById(R.id.add_via_email_text_field); emailText.setAdapter(new ArrayAdapter<String>(this, R.layout.list_item, new ArrayList<String>())); emailText.setThreshold(1); if (mService.isPermitted(Manifest.permission.READ_CONTACTS)) { mService.postAtFrontOfBIZZHandler(new SafeRunnable() { @SuppressWarnings("unchecked") @Override protected void safeRun() throws Exception { L.d("AddFriendsActivity getEmailAddresses"); List<String> emailList = ContactListHelper.getEmailAddresses(AddFriendsActivity.this); ArrayAdapter<String> a = (ArrayAdapter<String>) emailText.getAdapter(); for (int i = 0; i < emailList.size(); i++) { a.add(emailList.get(i)); } a.notifyDataSetChanged(); L.d("AddFriendsActivity gotEmailAddresses"); } }); } final SafeViewOnClickListener onClickListener = new SafeViewOnClickListener() { @Override public void safeOnClick(View v) { String email = emailText.getText().toString().trim(); if (RegexPatterns.EMAIL.matcher(email).matches()) { if (mFriendsPlugin.inviteFriend(email, null, null, true)) { emailText.setText(null); UIUtils.hideKeyboard(AddFriendsActivity.this, emailText); } else { UIUtils.showLongToast(AddFriendsActivity.this, getString(R.string.friend_invite_failed)); } } else { AlertDialog.Builder builder = new AlertDialog.Builder(AddFriendsActivity.this); builder.setMessage(R.string.registration_email_not_valid); builder.setPositiveButton(R.string.rogerthat, null); builder.create().show(); } } }; ((Button) findViewById(R.id.add_via_email_button)).setOnClickListener(onClickListener); emailText.setOnEditorActionListener(new OnEditorActionListener() { @Override public boolean onEditorAction(TextView view, int actionId, KeyEvent event) { if (actionId == EditorInfo.IME_ACTION_DONE || (event.getKeyCode() == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_DOWN)) { onClickListener.onClick(view); return true; } return false; } }); } private void inviteViaEmail(final Contact contact) { T.UI(); mFriendsPlugin.inviteFriend(contact.email, null, contact.getDisplayName(), true); } private void inviteViaSMS(final Contact contact) { T.UI(); MyIdentity identity = mService.getIdentityStore().getIdentity(); String shortLink = identity.getShortLink(); String installLink = CloudConstants.HTTPS_BASE_URL + CloudConstants.INSTALL_URL + "?a=" + AppConstants.APP_ID; String body; if (shortLink == null) { body = getString(R.string.friend_sms_invitation_no_url, contact.name, installLink, getString(R.string.app_name)); } else { Uri shortLinkUri = Uri.parse(shortLink); String shortLinkLC = shortLinkUri.getScheme().toLowerCase() + "://" + shortLinkUri.getHost().toLowerCase(); shortLink = shortLinkLC + shortLink.substring(shortLinkLC.length()); String secret = mFriendsPlugin.popInvitationSecret(); if (secret != null) { shortLink += "?s=" + secret; mFriendsPlugin.logInvitationSecretSent(secret, contact.email); } body = getString(R.string.friend_sms_invitation, contact.name, installLink, shortLink, getString(R.string.app_name)); } final SMSManager smsManager = new SMSManager(this); try { smsManager.sendSMS(contact.primaryPhoneNumber, body); } finally { smsManager.close(); } UIUtils.showLongToast(mService, mService.getString(R.string.invitation_sent_successfully)); mFriendsPlugin.getStore().insertPendingInvitation(contact.primaryPhoneNumber); } private Bitmap getAvatar(final Contact c, int type) { Bitmap avatar; switch (type) { case TYPE_AB_MATCH: case TYPE_SMS: case TYPE_MAIL: avatar = mPhoneContacts.getAvatar(c); break; case TYPE_FB_MATCH: final FacebookContact fbc = (FacebookContact) c; if (mFbAvatars.containsKey(fbc.email)) { avatar = mFbAvatars.get(fbc.email); } else { avatar = null; // Load avatar in the background L.d("Downloading fb avatar: " + fbc.pictureUrl); mFbAvatars.put(fbc.email, null); new SafeAsyncTask<Object, Object, Object>() { @Override protected Object safeDoInBackground(Object... params) { try { return BitmapFactory .decodeStream((InputStream) new URL((String) params[0]).getContent()); } catch (MalformedURLException e) { L.bug("Could not download Facebook avatar: " + fbc.pictureUrl, e); } catch (IOException e) { L.bug("Could not download Facebook avatar: " + fbc.pictureUrl, e); } catch (Exception e) { L.bug("Could not download Facebook avatar: " + fbc.pictureUrl, e); } return null; }; @Override protected void safeOnPostExecute(Object result) { Bitmap bitmap = (Bitmap) result; if (bitmap != null) { mFbAvatars.put(fbc.email, bitmap); ListView listView = (ListView) findViewById(R.id.add_via_facebook_result); BaseAdapter adapter = (BaseAdapter) listView.getAdapter(); adapter.notifyDataSetChanged(); } } @Override protected void safeOnCancelled(Object result) { } @Override protected void safeOnProgressUpdate(Object... values) { } @Override protected void safeOnPreExecute() { }; }.execute(fbc.pictureUrl); } break; default: avatar = null; break; } if (avatar == null) avatar = mFriendsPlugin.getMissingFriendAvatarBitmap(); else avatar = ImageHelper.getRoundedCornerAvatar(avatar); return avatar; } private void setContactOnView(final Contact c, final View v, final int type, final int btnDisabledText, final int btnEnabledText) { Bitmap avatar = getAvatar(c, type); ((ImageView) v.findViewById(R.id.avatar)).setImageBitmap(avatar); ((TextView) v.findViewById(R.id.name)).setText(c.name); final TextView contactMethod = (TextView) v.findViewById(R.id.secondary_label); contactMethod.setVisibility(type == TYPE_FB_MATCH ? View.GONE : View.VISIBLE); contactMethod.setText(type == TYPE_SMS ? c.primaryPhoneNumber : c.email); final Button btn = (Button) v.findViewById(R.id.invite_button); btn.setText(mPendingInvites.contains(c.email) ? btnDisabledText : btnEnabledText); btn.setEnabled(!mCurrentInvites.contains(c.email)); btn.setOnClickListener(new SafeViewOnClickListener() { @Override public void safeOnClick(View v) { btn.setEnabled(false); btn.setText(btnDisabledText); if (type == TYPE_SMS) { if (!mService.isPermitted(Manifest.permission.SEND_SMS)) { mCurrentContact = c; ActivityCompat.requestPermissions(AddFriendsActivity.this, new String[] { Manifest.permission.SEND_SMS }, SMSManager.MY_PERMISSIONS_REQUEST_SMS); return; } inviteViaSMS(c); } else { inviteViaEmail(c); } mPendingInvites.add(c.email); mCurrentInvites.add(c.email); } }); } @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { T.UI(); if (requestCode == SMSManager.MY_PERMISSIONS_REQUEST_SMS) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { inviteViaSMS(mCurrentContact); mCurrentContact = null; } } else if (requestCode == MY_PERMISSION_REQUEST_READ_CONTACTS) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { if (mFriendsPlugin.findRogerthatUsersViaAddressBook()) { displayContactsPage(1, null); } else { displayContactsPage(3, null); } } } } private class ContactsCursorAdapter extends CursorAdapter implements SectionIndexer { private final int mType; private final int mBtnEnabledText; private final int mBtnDisabledText; private final AlphabetIndexer mAlphaIndexer; public ContactsCursorAdapter(Cursor c, int type, int btnEnabledText, int btnDisabledText) { super(AddFriendsActivity.this, c, false); mType = type; mBtnEnabledText = btnEnabledText; mBtnDisabledText = btnDisabledText; mAlphaIndexer = new AlphabetIndexer(c, 1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); } @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { L.bug("Should not come here"); return null; } @Override public void bindView(View view, Context context, Cursor cursor) { L.bug("Should not come here"); } @Override public View getView(int position, View convertView, ViewGroup parent) { T.UI(); View v = convertView; if (v == null) { v = getLayoutInflater().inflate(R.layout.add_friends_list_item, parent, false); } getCursor().moveToPosition(position); final Contact c = mPhoneContacts.fromCursor(getCursor()); setContactOnView(c, v, mType, mBtnDisabledText, mBtnEnabledText); return v; } @Override public int getPositionForSection(int section) { return mAlphaIndexer.getPositionForSection(section); } @Override public int getSectionForPosition(int position) { return mAlphaIndexer.getSectionForPosition(position); } @Override public Object[] getSections() { return mAlphaIndexer.getSections(); } } private class ContactsListAdapter extends BaseAdapter { private final List<Contact> mContacts; private final int mType; private final int mBtnEnabledText; private final int mBtnDisabledText; public ContactsListAdapter(List<Contact> contacts, int type, int btnEnabledText, int btnDisabledText) { mContacts = contacts; mType = type; mBtnEnabledText = btnEnabledText; mBtnDisabledText = btnDisabledText; } @Override public int getCount() { T.UI(); return mContacts.size(); } @Override public Object getItem(int position) { T.UI(); return null; } @Override public long getItemId(int position) { T.UI(); return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { T.UI(); View v = convertView; if (v == null) { v = getLayoutInflater().inflate(R.layout.add_friends_list_item, parent, false); } final Contact c = mContacts.get(position); setContactOnView(c, v, mType, mBtnDisabledText, mBtnEnabledText); return v; } } private class FacebookContact extends Contact { public String pictureUrl; public FacebookContact(FacebookRogerthatProfileMatchTO matchTO) { this.email = matchTO.rtId; this.name = matchTO.fbName; this.pictureUrl = matchTO.fbPicture; } } }