/*
Copyright (c) Microsoft
All Rights Reserved
Apache 2.0 License
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.
See the Apache Version 2.0 License for specific language governing permissions and limitations under the License.
*/
package com.microsoft.aad.test.todoapi;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.List;
import java.util.TimeZone;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.azure.webapi.DateSerializer;
import com.azure.webapi.LongSerializer;
import com.azure.webapi.MobileServiceClient;
import com.azure.webapi.MobileServiceQueryOperations;
import com.azure.webapi.MobileServiceTable;
import com.azure.webapi.MobileServiceUser;
import com.azure.webapi.NextServiceFilterCallback;
import com.azure.webapi.ServiceFilter;
import com.azure.webapi.ServiceFilterRequest;
import com.azure.webapi.ServiceFilterResponse;
import com.azure.webapi.ServiceFilterResponseCallback;
import com.azure.webapi.TableOperationCallback;
import com.azure.webapi.TableQueryCallback;
import com.google.gson.GsonBuilder;
import com.microsoft.aad.adal.AuthenticationCallback;
import com.microsoft.aad.adal.AuthenticationContext;
import com.microsoft.aad.adal.AuthenticationResult;
import com.microsoft.aad.adal.CacheKey;
import com.microsoft.aad.adal.DefaultTokenCacheStore;
import com.microsoft.aad.adal.ITokenCacheStore;
import com.microsoft.aad.adal.TokenCacheItem;
public class ToDoActivity extends Activity {
private final static String TAG = "ToDoActivity";
public static final int MENU_LOGOUT = Menu.FIRST;
public static final int MENU_CLEAR_TOKEN = Menu.FIRST + 1;
public static final int MENU_GET_TOKEN = Menu.FIRST + 2;
public static final int MENU_GET_NEWSFEED = Menu.FIRST + 3;
public static final int MENU_GET_SETTINGS = Menu.FIRST + 4;
public static final int MENU_GET_LAYOUT_DEMO = Menu.FIRST + 5;
public static final int MENU_REFRESH_TOKEN_NORMAL = Menu.FIRST + 6;
public static final int MENU_REFRESH_TOKEN_DELAY = Menu.FIRST + 7;
/**
* ask to refresh and then fail to go to prompt to check the scenario where
* prompt screen shows up after user navigates to something else
*/
public static final int MENU_REFRESH_TOKEN_DELAY_PROMPT = Menu.FIRST + 8;
public static final int MENU_CANCEL_REQUEST = Menu.FIRST + 9;
public static final int MENU_SHOW_TOKEN = Menu.FIRST + 10;
public static final int MENU_EXPIRE_TOKEN = Menu.FIRST + 11;
private AuthenticationContext mAuthContext;
private int mLastRequestId = 0;
private boolean mSendCancel = false;
private boolean refreshInProgress = false;
/**
* Mobile Service Client reference
*/
private MobileServiceClient mClient;
/**
* Mobile Service Table used to access data
*/
private MobileServiceTable<WorkItem> mToDoTable = null;
/**
* Adapter to sync the items list with the view
*/
private WorkItemAdapter mAdapter = null;
/**
* EditText containing the "New ToDo" text
*/
private EditText mTextNewToDo;
/**
* Progress spinner to use for table operations
*/
private ProgressBar mProgressBar;
/**
* Show this dialog when activity first launches to check if user has login
* or not.
*/
private ProgressDialog mLoginProgressDialog;
private AuthenticationResult mToken;
private static int pickerYear;
private static int pickerMonth;
private static int pickerDayOfMonth;
TextView txtSummary;
/**
* Initializes the activity
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_to_do);
setDefaultDate();
Toast.makeText(getApplicationContext(), TAG + "LifeCycle: OnCreate", Toast.LENGTH_SHORT)
.show();
txtSummary = (TextView)findViewById(R.id.textViewTitle);
txtSummary.setText("TODO Services");
mProgressBar = (ProgressBar)findViewById(R.id.loadingProgressBar);
// Initialize the progress bar
mProgressBar.setVisibility(ProgressBar.GONE);
mLoginProgressDialog = new ProgressDialog(this);
mLoginProgressDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
mLoginProgressDialog.setMessage("Login in progress...");
mLoginProgressDialog.show();
refreshInProgress = false;
// Ask for token and provide callback
try {
Utils.setupKeyForSample();
mAuthContext = new AuthenticationContext(ToDoActivity.this, Constants.AUTHORITY_URL,
false);
mAuthContext.acquireToken(ToDoActivity.this, Constants.RESOURCE_ID,
Constants.CLIENT_ID, Constants.REDIRECT_URL, Constants.USER_HINT,
new AuthenticationCallback<AuthenticationResult>() {
@Override
public void onError(Exception exc) {
if (mLoginProgressDialog.isShowing()) {
mLoginProgressDialog.dismiss();
}
Toast.makeText(getApplicationContext(),
TAG + "getToken Error:" + exc.getMessage(), Toast.LENGTH_SHORT)
.show();
navigateToLogOut();
}
@Override
public void onSuccess(AuthenticationResult result) {
if (mLoginProgressDialog.isShowing()) {
mLoginProgressDialog.dismiss();
}
if (result != null && !result.getAccessToken().isEmpty()) {
setLocalToken(result);
sendRequest();
} else {
navigateToLogOut();
}
}
});
} catch (Exception e) {
Toast.makeText(getApplicationContext(), "Encryption is failed", Toast.LENGTH_SHORT)
.show();
}
Toast.makeText(getApplicationContext(), TAG + "done", Toast.LENGTH_SHORT).show();
}
private void setDefaultDate() {
final Calendar c = Calendar.getInstance();
// If user does not change the date, add button will use this date
pickerYear = c.get(Calendar.YEAR);
pickerMonth = c.get(Calendar.MONTH);
pickerDayOfMonth = c.get(Calendar.DAY_OF_MONTH);
}
private void sendRequest() {
if (refreshInProgress || mToken == null || mToken.getAccessToken().isEmpty())
return;
if (mClient == null) {
initAppTables();
}
refreshInProgress = true;
refreshItemsFromTable();
}
private URL getEndpointUrl() {
URL endpoint = null;
try {
endpoint = new URL(Constants.SERVICE_URL + "/api/" + Constants.TABLE_WORKITEM);
} catch (MalformedURLException e) {
e.printStackTrace();
}
return endpoint;
}
/**
* Register gson serializer for long and date type
*
* @return
*/
public static GsonBuilder createServiceGsonBuilder() {
GsonBuilder gsonBuilder = new GsonBuilder();
// Register custom date serializer/deserializer
gsonBuilder.registerTypeAdapter(Date.class, new DateSerializer());
LongSerializer longSerializer = new LongSerializer();
gsonBuilder.registerTypeAdapter(Long.class, longSerializer);
gsonBuilder.registerTypeAdapter(long.class, longSerializer);
gsonBuilder.serializeNulls();
return gsonBuilder;
}
private void initAppTables() {
try {
// Create the Mobile Service Client instance, using the provided
// Mobile Service URL
// TODO this is targeting single webapi controller
// each table should target different webapi controller
mClient = new MobileServiceClient(Constants.SERVICE_URL, ToDoActivity.this)
.withFilter(new ProgressFilter());
// When app is initializing, It needs token to continue. If not
// possible to get token without UI flow, it should direct to login
// screen so that
// user can see some instructions.
if (getLocalToken() != null) {
MobileServiceUser user = new MobileServiceUser();
user.setAuthenticationToken(getLocalToken().getAccessToken());
mClient.setCurrentUser(user);
} else {
navigateToLogOut();
return;
}
// Get the Mobile Service Table instance to use
mToDoTable = mClient.getTable(WorkItem.class);
mToDoTable.TABLES_URL = "/api/";
mTextNewToDo = (EditText)findViewById(R.id.textNewToDo);
// Create an adapter to bind the items with the view
mAdapter = new WorkItemAdapter(ToDoActivity.this, R.layout.row_list_to_do);
ListView listViewToDo = (ListView)findViewById(R.id.listViewToDo);
listViewToDo.setAdapter(mAdapter);
} catch (MalformedURLException e) {
createAndShowDialog(new Exception(
"There was an error creating the Mobile Service. Verify the URL"), "Error");
}
}
private void navigateToLogOut() {
// Show logout page
// Go to logout page
Intent intent = new Intent(ToDoActivity.this, LogOutActivity.class);
startActivity(intent);
// Close this activity
finish();
}
private void getToken(final AuthenticationCallback callback) {
// one of the acquireToken overloads
mAuthContext.acquireToken(ToDoActivity.this, Constants.RESOURCE_ID, Constants.CLIENT_ID,
Constants.REDIRECT_URL, Constants.USER_HINT, callback);
mLastRequestId = callback.hashCode();
}
private AuthenticationResult getLocalToken() {
return mToken;
}
private void setLocalToken(AuthenticationResult newToken) {
mToken = newToken;
}
/**
* Mark an item as completed
*
* @param item The item to mark
*/
public void checkItem(WorkItem item) {
if (mClient == null) {
return;
}
// Set the item as completed and update it in the table
item.setComplete(true);
final WorkItem itemRemove = item;
mToDoTable.update(item, new TableOperationCallback<WorkItem>() {
public void onCompleted(WorkItem entity, Exception exception,
ServiceFilterResponse response) {
if (exception == null) {
// We dont need to wait for entity in update operation
mAdapter.remove(itemRemove);
} else {
createAndShowDialog(exception, "Error");
}
}
});
}
public void updateDate(WorkItem item) {
if (mClient == null) {
return;
}
// Set the item as completed and update it in the table
mToDoTable.update(item, new TableOperationCallback<WorkItem>() {
public void onCompleted(WorkItem entity, Exception exception,
ServiceFilterResponse response) {
if (exception != null) {
createAndShowDialog(exception, "Error");
}
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
menu.add(Menu.NONE, MENU_LOGOUT, Menu.NONE, "LogOut for User");
menu.add(Menu.NONE, MENU_CLEAR_TOKEN, Menu.NONE, "Clear All Tokens");
menu.add(Menu.NONE, MENU_GET_TOKEN, Menu.NONE, "Get Token");
menu.add(Menu.NONE, MENU_GET_NEWSFEED, Menu.NONE, "Other Activity");
menu.add(Menu.NONE, MENU_GET_SETTINGS, Menu.NONE, "Test Settings");
menu.add(Menu.NONE, MENU_REFRESH_TOKEN_NORMAL, Menu.NONE, "RefreshNormal");
menu.add(Menu.NONE, MENU_REFRESH_TOKEN_DELAY, Menu.NONE, "RefreshDelay");
menu.add(Menu.NONE, MENU_REFRESH_TOKEN_DELAY_PROMPT, Menu.NONE, "RefreshDelayToPrompt");
menu.add(Menu.NONE, MENU_CANCEL_REQUEST, Menu.NONE, "CancelAuthentication");
menu.add(Menu.NONE, MENU_SHOW_TOKEN, Menu.NONE, "ShowTokens");
menu.add(Menu.NONE, MENU_EXPIRE_TOKEN, Menu.NONE, "Expire");
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_LOGOUT: {
resetTokens();
clearCookies();
// Go to logout page
Intent intent = new Intent(ToDoActivity.this, LogOutActivity.class);
startActivity(intent);
// dont finish since when it comes back this page can be used
// again
// if not discarded
return true;
}
case MENU_CLEAR_TOKEN: {
resetTokens();
clearCookies();
return true;
}
case MENU_GET_TOKEN:
getToken(new AuthenticationCallback<AuthenticationResult>() {
@Override
public void onError(Exception exc) {
Toast.makeText(getApplicationContext(), exc.getMessage(), Toast.LENGTH_LONG)
.show();
}
@Override
public void onSuccess(AuthenticationResult result) {
Toast.makeText(getApplicationContext(), "OnCompleted", Toast.LENGTH_LONG)
.show();
setLocalToken(result);
}
});
return true;
case MENU_GET_NEWSFEED: {
Intent intent = new Intent(ToDoActivity.this, FeedActivity.class);
startActivity(intent);
return true;
}
case MENU_GET_SETTINGS: {
Intent intent = new Intent(ToDoActivity.this, SettingsActivity.class);
startActivity(intent);
return true;
}
case MENU_REFRESH_TOKEN_NORMAL: {
refreshTokenNormal();
return true;
}
case MENU_REFRESH_TOKEN_DELAY: {
refreshTokenWithDelay(false);
return true;
}
case MENU_REFRESH_TOKEN_DELAY_PROMPT: {
refreshTokenWithDelay(true);
return true;
}
case MENU_CANCEL_REQUEST: {
// Clear tokens and then choose MENU_REFRESH_TOKEN_DELAY_PROMPT
// option.
// It will launch prompt screen with delay
//
sendCancelRequest();
return true;
}
case MENU_SHOW_TOKEN: {
showTokens();
return true;
}
default:
return super.onOptionsItemSelected(item);
}
}
private void clearCookies() {
CookieSyncManager.createInstance(ToDoActivity.this);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.removeAllCookie();
CookieSyncManager.getInstance().sync();
}
private void showTokens() {
ITokenCacheStore currentCache = mAuthContext.getCache();
if (currentCache != null && currentCache instanceof DefaultTokenCacheStore) {
DefaultTokenCacheStore cache = (DefaultTokenCacheStore)currentCache;
StringBuilder tokeninfo = new StringBuilder();
Iterator<TokenCacheItem> iterator = cache.getAll();
while (iterator.hasNext()) {
TokenCacheItem item = iterator.next();
tokeninfo.append("Key:" + CacheKey.createCacheKey(item).toString() + " Expires:"
+ item.getExpiresOn() + " token:" + item.getAccessToken().substring(0, 10)
+ "\n");
tokeninfo.append("--------------\n");
}
createAndShowDialog(tokeninfo.toString(), "Tokens");
}
}
private void refreshTokenNormal() {
setTokenExpire();
// reset cache to normal without delay
try {
mAuthContext = new AuthenticationContext(ToDoActivity.this, Constants.AUTHORITY_URL,
false);
txtSummary.setText("TODO Services sending services...");
// Normal token request will be send but it will have delay
getToken(new AuthenticationCallback<AuthenticationResult>() {
@Override
public void onError(Exception exc) {
Log.e(TAG, "refreshTokenNormal error" + exc.getMessage(), exc);
Toast.makeText(getApplicationContext(), exc.getMessage(), Toast.LENGTH_LONG)
.show();
}
@Override
public void onSuccess(AuthenticationResult result) {
if (isNotEmpty(result.getAccessToken()) && isNotEmpty(result.getRefreshToken())) {
Log.d(TAG, "refreshTokenNormal onSuccess");
} else {
Log.d(TAG, "refreshTokenNormal Problem....");
}
Toast.makeText(getApplicationContext(), "OnCompleted", Toast.LENGTH_LONG)
.show();
txtSummary.setText("TODO Services refreshed");
setLocalToken(result);
}
});
} catch (Exception e) {
Log.e(TAG, "Refresh token normal error", e);
Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
}
}
private boolean isNotEmpty(String value) {
return value != null && !value.isEmpty();
}
private void sendCancelRequest() {
mSendCancel = true;
// when activity is at the front cancel can be tested
}
private void refreshTokenWithDelay(boolean invalidateRefresh) {
ITokenCacheStore currentCache = mAuthContext.getCache();
// make token expired to force refresh token
TokenCacheItem item = currentCache.getItem(CacheKey.createCacheKey(Constants.AUTHORITY_URL,
Constants.RESOURCE_ID, Constants.CLIENT_ID, false, Constants.USER_HINT));
if (item != null) {
Calendar timeExpired = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
timeExpired.add(Calendar.MINUTE, -50);
item.setExpiresOn(timeExpired.getTime());
if (invalidateRefresh) {
item.setRefreshToken("invalidRefreshToken");
}
currentCache.setItem(CacheKey.createCacheKey(item), item);
}
try {
mAuthContext = new AuthenticationContext(ToDoActivity.this, Constants.AUTHORITY_URL,
false);
setNetworkDelayForDebugging(5000);
// Normal token request will be send, but it will have delay
getToken(new AuthenticationCallback<AuthenticationResult>() {
@Override
public void onError(Exception exc) {
Log.e(TAG, "refreshTokenWithDelay error" + exc.getMessage(), exc);
Toast.makeText(getApplicationContext(), exc.getMessage(), Toast.LENGTH_LONG)
.show();
// reset cache to normal without delay
try {
mAuthContext = new AuthenticationContext(ToDoActivity.this,
Constants.AUTHORITY_URL, false);
} catch (Exception e) {
Log.e(TAG, "refreshTokenWithDelay", e);
Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG)
.show();
}
setNetworkDelayForDebugging(0);
}
@Override
public void onSuccess(AuthenticationResult result) {
Log.d(TAG, "refreshTokenWithDelay onSuccess");
Toast.makeText(getApplicationContext(), "OnCompleted", Toast.LENGTH_LONG)
.show();
setLocalToken(result);
// reset cache to normal without delay
try {
mAuthContext = new AuthenticationContext(ToDoActivity.this,
Constants.AUTHORITY_URL, false);
} catch (Exception e) {
Log.e(TAG, "refreshTokenWithDelay", e);
Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG)
.show();
}
setNetworkDelayForDebugging(0);
}
});
} catch (Exception e) {
Log.e(TAG, "Refresh token with delay", e);
Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
}
}
private void setNetworkDelayForDebugging(int miliSeconds) {
// HttpWebRequest class has a static field to use to introduce delays in
// debugger mode
Log.d(TAG, "setNetworkDelayForDebugging:" + miliSeconds);
Class<?> c = null;
Field field;
try {
c = Class.forName("com.microsoft.adal.HttpWebRequest");
field = c.getDeclaredField("sDebugSimulateDelay");
field.setAccessible(true);
field.set(null, miliSeconds);
} catch (Exception e) {
// TODO Auto-generated catch block
Log.d(TAG, "Reflection issue");
e.printStackTrace();
}
}
private void setTokenExpire() {
// get items and set them to expired from cache
// default cache is in use by default
ITokenCacheStore currentCache = mAuthContext.getCache();
String key = CacheKey.createCacheKey(Constants.AUTHORITY_URL, Constants.RESOURCE_ID,
Constants.CLIENT_ID, false, Constants.USER_HINT);
TokenCacheItem item = currentCache.getItem(key);
if (item != null) {
Calendar timeExpired = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
timeExpired.add(Calendar.MINUTE, -50);
item.setExpiresOn(timeExpired.getTime());
currentCache.setItem(key, item);
}
}
@Override
public void onResume() {
super.onResume(); // Always call the superclass method first
// User can click logout, it will come back here
// It should refresh list again
refreshInProgress = false;
sendRequest();
}
@Override
protected void onRestart() {
super.onRestart();
}
@Override
protected void onPause() {
super.onPause();
Log.d(TAG, "TODOActivity onPause");
if (mSendCancel) {
// refresh token will have delay and then this will send cancel
// request
// to the authenticationActivity
final Runnable r = new Runnable() {
@Override
public void run() {
Log.d(TAG, "Sending cancel request for requestId:" + mLastRequestId);
boolean result = mAuthContext.cancelAuthenticationActivity(mLastRequestId);
Log.d(TAG, "Result from cancel request:" + result);
}
};
// Manual tests: adjust timing to catch when activity launches
new Handler().postDelayed(r, 5000);
mSendCancel = false;
}
}
@Override
protected void onStop() {
super.onStop();
}
@Override
protected void onDestroy() {
super.onDestroy();
Toast.makeText(getApplicationContext(), TAG + "LifeCycle: OnDestroy", Toast.LENGTH_SHORT)
.show();
}
private void resetTokens() {
// Clear auth context tokens and local field as well
mAuthContext.getCache().removeAll();
mToken = null;
// clear token from current user obj
if (mClient != null) {
MobileServiceUser user = mClient.getCurrentUser();
if (user != null) {
user.setAuthenticationToken(null);
}
}
}
/*
* Target SDK above 11 for fragments
*/
public void showDatePicker(View v) {
DialogFragment newFragment = new DatePickerFragment();
newFragment.show(getFragmentManager(), "datePicker");
}
/*
* Datepicker to set duedate
*/
public static class DatePickerFragment extends DialogFragment implements
DatePickerDialog.OnDateSetListener {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Create a new instance of DatePickerDialog and return it
return new DatePickerDialog(getActivity(), this, pickerYear, pickerMonth,
pickerDayOfMonth);
}
public void onDateSet(DatePicker view, int year, int month, int day) {
// Update current selected date to be used in add post
// there is only one item posting
pickerYear = year;
pickerMonth = month;
pickerDayOfMonth = day;
}
}
/**
* Add a new item
*
* @param view The view that originated the call
*/
public void addItem(View view) {
if (mClient == null) {
initAppTables();
}
if (getLocalToken() != null) {
MobileServiceUser user = new MobileServiceUser();
user.setAuthenticationToken(getLocalToken().getAccessToken());
mClient.setCurrentUser(user);
}
if (pickerYear == 0 && pickerMonth == 0 && pickerDayOfMonth == 0) {
setDefaultDate();
}
// Create a new item
WorkItem item = new WorkItem();
// Get title from edit text field
item.setTitle(mTextNewToDo.getText().toString());
// Checkbox set to false
item.setComplete(false);
Calendar calendar = Calendar.getInstance();
calendar.set(pickerYear, pickerMonth, pickerDayOfMonth);
item.setDueDate(calendar.getTime());
// Insert the new item
mToDoTable.insert(item, new TableOperationCallback<WorkItem>() {
public void onCompleted(WorkItem entity, Exception exception,
ServiceFilterResponse response) {
if (exception == null) {
if (!entity.isComplete()) {
mAdapter.add(entity);
}
} else {
createAndShowDialog(exception, "Error");
}
}
});
mTextNewToDo.setText("");
}
public void refreshItem(View view) {
if (mClient == null) {
return;
}
// Load the items from the Mobile Service
refreshItemsFromTable();
}
/**
* Refresh the list with the items in the Mobile Service Table
*/
private void refreshItemsFromTable() {
// Get the items that weren't marked as completed and add them in the
// adapter
if (getLocalToken() != null) {
MobileServiceUser user = new MobileServiceUser();
user.setAuthenticationToken(getLocalToken().getAccessToken());
mClient.setCurrentUser(user);
}
if (mToDoTable != null) {
mToDoTable.where().field("Complete").eq(MobileServiceQueryOperations.val(false))
.execute(new TableQueryCallback<WorkItem>() {
public void onCompleted(List<WorkItem> result, int count,
Exception exception, ServiceFilterResponse response) {
if (exception == null) {
mAdapter.clear();
for (WorkItem item : result) {
mAdapter.add(item);
}
} else {
createAndShowDialog(exception, "Error");
}
}
});
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
mAuthContext.onActivityResult(requestCode, resultCode, data);
}
/**
* Creates a dialog and shows it
*
* @param exception The exception to show in the dialog
* @param title The dialog title
*/
private void createAndShowDialog(Exception exception, String title) {
createAndShowDialog(exception.toString(), title);
}
/**
* Creates a dialog and shows it
*
* @param message The dialog message
* @param title The dialog title
*/
private void createAndShowDialog(String message, String title) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(message);
builder.setTitle(title);
builder.create().show();
}
private class ProgressFilter implements ServiceFilter {
@Override
public void handleRequest(ServiceFilterRequest request,
NextServiceFilterCallback nextServiceFilterCallback,
final ServiceFilterResponseCallback responseCallback) {
runOnUiThread(new Runnable() {
@Override
public void run() {
if (mProgressBar != null)
mProgressBar.setVisibility(ProgressBar.VISIBLE);
}
});
nextServiceFilterCallback.onNext(request, new ServiceFilterResponseCallback() {
@Override
public void onResponse(ServiceFilterResponse response, Exception exception) {
runOnUiThread(new Runnable() {
@Override
public void run() {
if (mProgressBar != null)
mProgressBar.setVisibility(ProgressBar.GONE);
}
});
if (responseCallback != null)
responseCallback.onResponse(response, exception);
}
});
}
}
@Override
@Deprecated
public Object onRetainNonConfigurationInstance() {
return mAuthContext;
}
}