Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing onActivityResult in Cordova

Does Cordova have any automatic way to pass onActivityResult to its CordovaPlugin classes?

Here's my current file, doing it manually:

package com.myapp;

import android.os.Bundle;
import org.apache.cordova.*;

import android.content.Intent;

import com.flyingsoftgames.googleplaytoken.GooglePlayToken;

public class MyApp extends CordovaActivity {

 @Override protected void onActivityResult (int requestCode, int resultCode, Intent data) {
  GooglePlayToken.runOnActivityResult (requestCode, resultCode, data);
 }

 @Override public void onCreate (Bundle savedInstanceState) {
  super.onCreate (savedInstanceState);
  super.init ();
  super.loadUrl(Config.getStartUrl());
 }
}


I tried to use the same technique employed in https://github.com/apache/cordova-plugin-camera/blob/master/src/android/CameraLauncher.java to get the data passed through "automatically" -- but it crashes. Here is a working (manual and no data pass-through) and non-working (automatic data pass-through) version of the target class. First working, then non-working.

Working, no data pass-through:

// Working, no data pass-through.
package com.flyingsoftgames.googleplaytoken;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.Scopes;

import com.google.android.gms.auth.GoogleAuthException;
import com.google.android.gms.auth.GoogleAuthUtil;
import com.google.android.gms.auth.UserRecoverableAuthException;

import com.google.android.gms.common.AccountPicker;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.PluginResult;
import org.apache.cordova.PluginResult.Status;

import org.json.JSONArray;
import org.json.JSONException;

import android.content.Context;
import android.content.Intent;

import android.app.Activity;
import android.accounts.AccountManager;

import android.os.AsyncTask;
import android.os.Bundle;

import java.io.IOException;

import android.util.Log;

public class GooglePlayToken extends CordovaPlugin {

 private static final String LOG_TAG = "GooglePlayToken";
 private static final int REQ_SIGN_IN_REQUIRED = 55664;

 public static CordovaInterface cordova           = null;
 public static CallbackContext tryConnectCallback = null;
 public static String          accessToken        = "";

 public static final int REQUEST_CODE_PICK_ACCOUNT = 1000;

 @Override public void initialize (CordovaInterface initCordova, CordovaWebView webView) {
  cordova = initCordova;
  super.initialize (cordova, webView);
 }

 private void pickUserAccount () {
  String[] accountTypes = new String[]{"com.google"};
  Intent intent = AccountPicker.newChooseAccountIntent(null, null, accountTypes, false, null, null, null, null);
  cordova.getActivity().startActivityForResult (intent, REQUEST_CODE_PICK_ACCOUNT);
 }

 public static void runOnActivityResult (int requestCode, int resultCode, Intent data) {
  if ((requestCode == REQUEST_CODE_PICK_ACCOUNT) && (resultCode == Activity.RESULT_OK)) {
   new RetrieveTokenTask().execute (data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME));
  }
 }

 public boolean execute (String action, JSONArray inputs, CallbackContext callbackContext) throws JSONException {
 if ("tryConnect".equals(action)) {
   tryConnect (callbackContext);
  } else if ("getAccessToken".equals(action)) {
   callbackContext.sendPluginResult (new PluginResult (PluginResult.Status.OK, accessToken));
  }
  return true;
 }

 // tryConnect runs the callback with a value of false if Google Play Services isn't available.
 public void tryConnect (CallbackContext callbackContext) {
  tryConnectCallback = callbackContext;
  pickUserAccount ();
 }


 private static class RetrieveTokenTask extends AsyncTask<String, Void, String> {
  @Override protected String doInBackground (String... params) {
   String accountName = params[0];
   String scope = "oauth2:" + Scopes.PROFILE;
   Context context = cordova.getActivity().getApplicationContext();
   try {
    accessToken = GoogleAuthUtil.getToken(context, accountName, scope);
   } catch (IOException e) {
    String errormessage = e.getMessage();
    if (tryConnectCallback != null) tryConnectCallback.error ("Error: " + errormessage + "."); tryConnectCallback = null;
   } catch (UserRecoverableAuthException e) {
    cordova.getActivity().startActivityForResult (e.getIntent(), REQ_SIGN_IN_REQUIRED);
   } catch (GoogleAuthException e) {
    String errormessage = e.getMessage();
    if (tryConnectCallback != null) tryConnectCallback.error ("Error: " + errormessage + "."); tryConnectCallback = null;
   }
   return accessToken;
  }

  @Override protected void onPostExecute (String newAccessToken) {
   super.onPostExecute (newAccessToken);
   accessToken = newAccessToken;
   if (tryConnectCallback != null) {
    tryConnectCallback.sendPluginResult (new PluginResult (PluginResult.Status.OK, accessToken));
    tryConnectCallback = null;
   }
  }
 }
}


Non-working, data pass-through:

// Crashy / non-working, data pass-through.
package com.flyingsoftgames.googleplaytoken;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.Scopes;

import com.google.android.gms.auth.GoogleAuthException;
import com.google.android.gms.auth.GoogleAuthUtil;
import com.google.android.gms.auth.UserRecoverableAuthException;

import com.google.android.gms.common.AccountPicker;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.PluginResult;
import org.apache.cordova.PluginResult.Status;

import org.json.JSONArray;
import org.json.JSONException;

import android.content.Context;
import android.content.Intent;

import android.app.Activity;
import android.accounts.AccountManager;

import android.os.AsyncTask;
import android.os.Bundle;

import java.io.IOException;

import android.util.Log;

public class GooglePlayToken extends CordovaPlugin {

 private final String LOG_TAG = "GooglePlayToken";
 private final int REQ_SIGN_IN_REQUIRED = 55664;

 public CordovaInterface cordova           = null;
 public CallbackContext tryConnectCallback = null;
 public String          accessToken        = "";

 public final int REQUEST_CODE_PICK_ACCOUNT = 1000;

 @Override public void initialize (CordovaInterface initCordova, CordovaWebView webView) {
 Log.e (LOG_TAG, "initialize");
  cordova = initCordova;
  super.initialize (cordova, webView);
 }

 private void pickUserAccount () {
  Log.e (LOG_TAG, "pickUserAccount");
  String[] accountTypes = new String[]{"com.google"};
  Intent intent = AccountPicker.newChooseAccountIntent(null, null, accountTypes, false, null, null, null, null);
  //cordova.startActivityForResult ((CordovaPlugin) this, intent, REQUEST_CODE_PICK_ACCOUNT); // Tried this, too.
  cordova.getActivity().startActivityForResult (intent, REQUEST_CODE_PICK_ACCOUNT);
 }

 //public static void runOnActivityResult (int requestCode, int resultCode, Intent data) {
 public void onActivityResult(int requestCode, int resultCode, Intent intent) {
  Log.e (LOG_TAG, "runOnActivityResult");
  if ((requestCode == REQUEST_CODE_PICK_ACCOUNT) && (resultCode == Activity.RESULT_OK)) {
   new RetrieveTokenTask().execute (intent.getStringExtra(AccountManager.KEY_ACCOUNT_NAME));
  }
 }

 public boolean execute (String action, JSONArray inputs, CallbackContext callbackContext) throws JSONException {
 Log.e (LOG_TAG, "execute: " + action);
 if ("tryConnect".equals(action)) {
   tryConnect (callbackContext);
  } else if ("getAccessToken".equals(action)) {
   callbackContext.sendPluginResult (new PluginResult (PluginResult.Status.OK, accessToken));
  }
  return true;
 }

 // tryConnect runs the callback with a value of false if Google Play Services isn't available.
 public void tryConnect (CallbackContext callbackContext) {
  Log.e (LOG_TAG, "tryConnect");
  tryConnectCallback = callbackContext;
  pickUserAccount ();
 }


 private class RetrieveTokenTask extends AsyncTask<String, Void, String> {
  @Override protected String doInBackground (String... params) {
   Log.e (LOG_TAG, "RetrieveTokenTask");
   String accountName = params[0];
   String scope = "oauth2:" + Scopes.PROFILE;
   Context context = cordova.getActivity().getApplicationContext();
   try {
    accessToken = GoogleAuthUtil.getToken(context, accountName, scope);
    GoogleAuthUtil.clearToken (context, accessToken);
    accessToken = GoogleAuthUtil.getToken(context, accountName, scope);
    Log.e (LOG_TAG, accessToken);
   } catch (IOException e) {
    String errormessage = e.getMessage();
    if (tryConnectCallback != null) tryConnectCallback.error ("Error: " + errormessage + "."); tryConnectCallback = null;
   } catch (UserRecoverableAuthException e) {
    cordova.getActivity().startActivityForResult (e.getIntent(), REQ_SIGN_IN_REQUIRED);
   } catch (GoogleAuthException e) {
    String errormessage = e.getMessage();
    if (tryConnectCallback != null) tryConnectCallback.error ("Error: " + errormessage + "."); tryConnectCallback = null;
   }
   return accessToken;
  }

  @Override protected void onPostExecute (String newAccessToken) {
   super.onPostExecute (newAccessToken);
   accessToken = newAccessToken;
   if (tryConnectCallback != null) {
    tryConnectCallback.sendPluginResult (new PluginResult (PluginResult.Status.OK, accessToken));
    tryConnectCallback = null;
   }
  }
 }
}
like image 574
Agamemnus Avatar asked Dec 03 '14 20:12

Agamemnus


1 Answers

Turns out that all I needed to do was to run cordova.setActivityResultCallback (this); before cordova.getActivity().startActivityForResult (intent, REQUEST_CODE_PICK_ACCOUNT);.

like image 76
Agamemnus Avatar answered Nov 15 '22 23:11

Agamemnus