package com.androidcookbook.oauth2demo;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountManagerCallback;
import android.accounts.AccountManagerFuture;
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.darwinsys.net.ConversationURL;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private static final String AUTHDOM_RO = "View your tasks",
AUTHDOM_RW = "Manage your tasks";
private String authToken;
private final static int MY_PERMISSIONS_REQUEST_GET_ACCOUNTS = 1;
String our_api_key, our_client_id, our_client_secret;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(MainActivity.this, "Someday that button will add tasks", Toast.LENGTH_SHORT).show();
}
});
}
public void getTasks(View v) {
getTasks();
}
public void getTasks() {
Log.d(TAG, "MainActivity.getTasks()");
AccountManager am = AccountManager.get(this);
// We really need GET_ACCOUNT permission, so we can get the Google account
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.GET_ACCOUNTS)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{android.Manifest.permission.GET_ACCOUNTS},
MY_PERMISSIONS_REQUEST_GET_ACCOUNTS);
return; // Will have to try later.
}
final Account[] accounts = am.getAccounts();
if (accounts.length == 0) {
Toast.makeText(this, "Please create a Google account before using this app", Toast.LENGTH_LONG).show();
finish();
return;
}
for (Account acct : accounts) {
Log.d(TAG, "Account " + acct.name + "(" + acct.type + ")");
if (acct.type.equals("com.google")) {
Bundle options = new Bundle();
am.invalidateAuthToken(acct.type, authToken);
// Get the auth authToken. Doesn't return a value; find it in the callbacks
am.getAuthToken(
acct, // Android "Account" for Google access
AUTHDOM_RO, // Google-provided Auth scope for viewing tasks
options, // If any authenticator-specific options needed, pass here
MainActivity.this,
new OnTokenAcquired(), // Success Callback
new Handler(new OnError())); // Failure Callback
break;
}
}
}
/**
* This is part of getting permission just to access the user's Google account
*
* @param requestCode Passed in
* @param permissions The list of permissions we asked for (only 1)
* @param grantResults The results (only 1)
*/
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_GET_ACCOUNTS:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Success, do the operation
getTasks();
} else {
// Nothing we can do in the "permission denied" case??
}
return;
default:
Log.d(TAG, "Unexpected requestCode " + requestCode);
}
}
/**
* Callback indicates that OAuth2 authenticator has got an Auth Token for us,
* so save it in a member property for use in the REST service code,
* and invoke same.
*/
private class OnTokenAcquired implements AccountManagerCallback<Bundle> {
@Override
public void run(AccountManagerFuture<Bundle> result) {
Log.d(TAG, "OnTokenAcquired.run()");
// Get the result of the operation from the AccountManagerFuture.
try {
Bundle bundle = result.getResult();
// The authToken is a named value in the bundle. The name of the value
// is stored in the constant AccountManager.KEY_AUTHTOKEN.
authToken = bundle.getString(AccountManager.KEY_AUTHTOKEN);
Log.d(TAG, "Got this authToken: " + authToken);
doFetchTaskList();
} catch (OperationCanceledException e) {
// Nothing to do
} catch (IOException e) {
// handle this error!
e.printStackTrace();
} catch (AuthenticatorException e) {
// handle this error!
e.printStackTrace();
}
}
}
private class OnError implements Handler.Callback {
@Override
public boolean handleMessage(Message message) {
Log.wtf(TAG, "ERROR: " + message.toString());
Toast.makeText(MainActivity.this, message.toString(), Toast.LENGTH_LONG).show();
return false;
}
}
/**
* Finally! We have an Auth Token, so go ahead and invokve the service
*/
void doFetchTaskList() {
// Now we have to fetch the list of Tasks for this user
try {
URL url =
new URL("https://www.googleapis.com/tasks/v1/users/@me/lists/@default/tasks?key=" + our_api_key);
Map<String,String> headers = new HashMap<>();
headers.put("accept", "text/json");
headers.put("authorization", "OAuth " + authToken);
headers.put("client_id", our_client_id);
headers.put("client_secret", our_client_secret);
final String tasks = ConversationURL.converse(url, null, headers);
Log.d(TAG, "Got this list of tasks: " + tasks);
// Convert to List<Task> using some JSON API
// Display list in a RecyclerView or ListView
} catch (IOException e) {
throw new RuntimeException("Get task list failed: " + e, e);
}
}
}