本文概述
如果你使用的是使用第三方API的插件, 并且不能随意修改其代码, 则可能会发现使用onActivityResult函数从api检索结果的代码。
好吧, 如果你在任何Android项目上工作, 这根本没有问题, 但是如果你尝试在Cordova插件上完成此任务, 那么你可能现在想杀死自己, 因为它根本不起作用。因此, 请不要这样做, 至少今天不要这样做。
也许你已经注意到(很明显地知道)此问题是由于主Cordova活动(由于某种原因)没有被触发, 并且你无法覆盖此方法。因此, 从理论上讲, 解决方案非常简单, 只需创建一个意图并将事件委托给该意图, 然后使用cordova.startActivityForResult在cordova中检索该事件即可。
在下面的示例中, 我们将以OneDrive文件选择器为例。
解
如前所述, 你不能简单地在同一Cordova Activity中覆盖onActivityResult, 因此, 我们将创建一个用于启动Filepicker的Empty View(新意图)。为了创建一个空的活动, 在你的plugin.xml文件中添加以下标记以创建一个可用的视图(稍后我们将使用Java类对其进行操作)。在这种情况下, 名称为DialogShowPicker(该Intent必须具有与Java类相同的名称), 请注意, 它必须位于android platform标签内:
<platform name="android">
<!--This will be the activity, if you want another name change in both of the tags (action and activity) -->
<config-file target="AndroidManifest.xml" parent="/manifest/application">
<activity android:name="com.ourcodeworld.plugins.onedrivefilepicker.DialogShowPicker"
android:label="OneDrive filepicker">
<intent-filter>
<!-- We are going to use this name to start the activity later in Java -->
<action android:name="com.ourcodeworld.plugins.onedrivefilepicker.DialogShowPicker" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</config-file>
</platform>
那应该在项目中创建活动, 我们可以在主类中调用它。你只需要创建一个新的Intent, 指定活动的名称(我们之前在plugin.xml文件中提供的名称), 然后将其作为参数发送给cordova.startActivityForResult, 它将为你解决问题。
转到你的主类的execute函数并处理上述算法。遵循以下示例:
package com.ourcodeworld.plugins.onedrivefilepicker;// Change the package name according to your plugin.
import org.apache.cordova.*;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.Intent;
import android.content.Context;// To toast
import android.widget.Toast;// ToToast
import android.os.Bundle;
public class myPluginMainClass extends CordovaPlugin {
private static final String ACTION_SHOWPICKER = "showpicker";
private CallbackContext PUBLIC_CALLBACKS = null;
@Override
public boolean execute(String action, JSONArray data, CallbackContext callbackContext) throws JSONException {
final JSONObject arg_object = data.getJSONObject(0);
String ONEDRIVE_APP_ID = "thisisTheAppIdfortheExample";
String LINK_MODE = "download";
PUBLIC_CALLBACKS = callbackContext;
// If the showpicker action is executed from javascript, start the activity that starts the picker
if (ACTION_SHOWPICKER.equals(action)) {
// The intent expects as first parameter the given name for the activity in your plugin.xml
Intent intent = new Intent("com.ourcodeworld.plugins.onedrivefilepicker.DialogShowPicker");
// Send some info to the activity to retrieve it later
intent.putExtra("app_id", ONEDRIVE_APP_ID);
intent.putExtra("link_mode", LINK_MODE);
// Now, cordova will expect for a result using startActivityForResult and will be handle by the onActivityResult.
cordova.startActivityForResult((CordovaPlugin) this, intent, 0);
}
// Send no result, to execute the callbacks later
PluginResult pluginResult = new PluginResult(PluginResult.Status.NO_RESULT);
pluginResult.setKeepCallback(true); // Keep callback
return true;
}
@Override
public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
if(resultCode == cordova.getActivity().RESULT_OK){
Bundle extras = data.getExtras();// Get data sent by the Intent
String information = extras.getString("data"); // data parameter will be send from the other activity.
tolog(information); // Shows a toast with the sent information in the other class
PluginResult resultado = new PluginResult(PluginResult.Status.OK, "this value will be sent to cordova");
resultado.setKeepCallback(true);
PUBLIC_CALLBACKS.sendPluginResult(resultado);
return;
}else if(resultCode == cordova.getActivity().RESULT_CANCELED){
PluginResult resultado = new PluginResult(PluginResult.Status.OK, "canceled action, process this in javascript");
resultado.setKeepCallback(true);
PUBLIC_CALLBACKS.sendPluginResult(resultado);
return;
}
// Handle other results if exists.
super.onActivityResult(requestCode, resultCode, data);
}
// A function to show a toast with some data, just demo
public void tolog(String toLog){
Context context = cordova.getActivity();
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, toLog, duration);
toast.show();
}
}
现在我们需要处理活动开始时将发生的情况。在你的android代码中创建Java类(DialogShowPicker.java), 不要忘记将其包含在插件中。 java类应如下所示:
package com.ourcodeworld.plugins.onedrivefilepicker;// Change the package name acording to your plugin name
import org.apache.cordova.*;
import android.app.Activity;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.Intent;
import android.os.Bundle;
import com.microsoft.onedrivesdk.picker.*;
public class DialogShowPicker extends Activity{
private boolean firstTime = true;
@Override
public void onStart() {
super.onStart();
// Write your code inside this condition
// Here should start the process that expects the onActivityResult
if(firstTime == true){
// Do something at first initialization
// And retrieve the parameters that we sent before in the Main file of the plugin
Bundle extras = getIntent().getExtras();
if (extras != null) {
String appId = extras.getString("app_id");
linkMode = extras.getString("link_mode");
mPicker = Picker.createPicker(appId);
// startPicking method will execute onActivityResult whe na file is selected.
if(linkMode.equals("view")){
mPicker.startPicking(this, LinkType.WebViewLink);
}else if(linkMode.equals("download")){
mPicker.startPicking(this, LinkType.DownloadLink);
}
}
}
}
@Override
public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
firstTime = false;// There's a result, allow to exit the activity !
// Do something with the result of the Intent data
// Send parameters to retrieve in cordova.
Intent intent = new Intent();
intent.putExtra("data", "This is the sent information from the 2 activity :) ");
setResult(Activity.RESULT_OK, intent);
finish();// Exit of this activity !
}
}
并使用将其添加到你的插件中:
<!-- Change target-dir according to your plugin -->
<source-file src="src/android/DialogShowPicker.java" target-dir="src/com/ourcodeworld/plugin/"/>
然后, 只需使用javascript(你应在插件中根据需要自行定义)执行函数即可。你可以查看下图以了解我们刚刚完成的工作:
笔记
- 你只能在Intent(字符串和数字)之间发送原始值
玩得开心