I downloaded the source for the activty starter and made an rush extention to do it. Here is the code, the result event does not work because rush would not compile the extention if it was present feel free to close this thread. I apologize but I had to make it quickly for a project. so it is a bit rough around the edges. I apologize for that.
package com.test.StarterV2;
import com.google.appinventor.components.annotations.SimpleFunction;
import com.google.appinventor.components.runtime.AndroidNonvisibleComponent;
import com.google.appinventor.components.runtime.ComponentContainer;
import com.google.appinventor.components.runtime.errors.YailRuntimeError;
import com.google.appinventor.components.runtime.util.YailList;
import android.app.Activity;
import android.app.Activity;
import android.content.Context;
import com.google.appinventor.components.annotations.*;
import com.google.appinventor.components.common.ComponentCategory;
import com.google.appinventor.components.runtime.AndroidNonvisibleComponent;
import com.google.appinventor.components.runtime.ComponentContainer;
import com.google.appinventor.components.runtime.EventDispatcher;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
import com.google.appinventor.components.annotations.DesignerProperty;
import com.google.appinventor.components.annotations.PropertyCategory;
import com.google.appinventor.components.annotations.SimpleEvent;
import com.google.appinventor.components.annotations.SimpleFunction;
import com.google.appinventor.components.annotations.SimpleProperty;
import com.google.appinventor.components.common.ComponentCategory;
import com.google.appinventor.components.common.PropertyTypeConstants;
import com.google.appinventor.components.runtime.errors.YailRuntimeError;
import com.google.appinventor.components.runtime.util.AnimationUtil;
import com.google.appinventor.components.runtime.util.ErrorMessages;
import com.google.appinventor.components.runtime.util.NougatUtil;
import com.google.appinventor.components.runtime.util.YailList;
import java.io.File;
public class StarterV2 extends AndroidNonvisibleComponent{
private String action;
private String dataUri;
private String dataType;
private String activityPackage;
private String activityClass;
private String extraKey;
private String extraValue;
private String resultName;
private Intent resultIntent;
private String result;
private int requestCode;
private YailList extras;
private final ComponentContainer container;
private static final String LOG_TAG = "ActivityStarter";
public StarterV2(ComponentContainer container) {
super(container.$form());
// Save the container for later
this.container = container;
result = "";
Action(Intent.ACTION_MAIN);
ActivityPackage("");
ActivityClass("");
DataUri("");
DataType("");
ExtraKey("");
ExtraValue("");
Extras(new YailList());
ResultName("");
}
/**
* Returns the action that will be used to start the activity.
*/
@SimpleProperty(
)
public String Action() {
return action;
}
/**
* Specifies the action that will be used to start the activity.
*/
@DesignerProperty(editorType = PropertyTypeConstants.PROPERTY_TYPE_STRING,
defaultValue = "")
@SimpleProperty
public void Action(String action) {
this.action = action.trim();
}
// TODO(lizlooney) - currently we support just one extra name/value pair that will be passed to
// the activity. The user specifies the ExtraKey and ExtraValue properties.
// We should allow more extra name/value pairs, but we'd need a different interface with regard
// to properties and functions.
// In the documentation for Intent, they use the term "name", not "key", and we might want to use
// the term "name", also.
// There are backwards compatibility issues with removing the ExtraKey and ExtraValue properties.
// Also, while extra names are always Strings, the values can be other types. We'd need to know
// the correct type of the value in order to call the appropriate Intent.putExtra method.
// Adding multiple functions like PutStringExtra, PutStringArrayExtra, PutCharExtra,
// PutCharArrayExtra, PutBooleanExtra, PutBooleanArrayExtra, PutByteExtra, PutByteArrayExtra,
// PutShortExtra, PutShortArrayExtra, PutIntExtra, PutIntArrayExtra, PutLongExtra,
// PutLongArrayExtra, PutFloatExtra, PutFloatArrayExtra, PutDoubleExtra, PutDoubleArrayExtra,
// etc, seems like a bad idea.
/**
* Returns the extra key that will be passed to the activity.
* Obsolete. Should use Extras instead
*/
@SimpleProperty()
public String ExtraKey() {
return extraKey;
}
/**
* Specifies the extra key that will be passed to the activity.
* Obsolete. Should use Extras instead
*/
@DesignerProperty(editorType = PropertyTypeConstants.PROPERTY_TYPE_STRING,
defaultValue = "")
@SimpleProperty
public void ExtraKey(String extraKey) {
this.extraKey = extraKey.trim();
}
/**
* Returns the extra value that will be passed to the activity.
* Obsolete. Should use Extras instead
*/
@SimpleProperty()
public String ExtraValue() {
return extraValue;
}
/**
* Specifies the extra value that will be passed to the activity.
* Obsolete. Should use Extras instead
*/
@DesignerProperty(editorType = PropertyTypeConstants.PROPERTY_TYPE_STRING,
defaultValue = "")
@SimpleProperty
public void ExtraValue(String extraValue) {
this.extraValue = extraValue.trim();
}
// TODO(lizlooney) - currently we support retrieving just one string extra result from the
// activity. The user specifies the ResultName property and, then after the activity finishes,
// the string extra result corresponding to ResultName is passed as the result parameter to the
// AfterActivity event and is also available from the Result property getter.
// We should allow access to more extra results, but we'd need a different interface with regard
// to properties, functions, and events parameters.
// There are backwards compatibility issues with removing the AfterActivity event's result
// parameter and the Result property.
// Also, while extra names are always Strings, the values can be other types. We'd need to know
// the correct type of the value in order to call the appropriate Intent.get...Extra method.
// Adding multiple functions like GetStringExtra, GetStringArrayExtra, GetCharExtra,
// GetCharArrayExtra, GetBooleanExtra, GetBooleanArrayExtra, GetByteExtra, GetByteArrayExtra,
// GetShortExtra, GetShortArrayExtra, GetIntExtra, GetIntArrayExtra, GetLongExtra,
// GetLongArrayExtra, GetFloatExtra, GetFloatArrayExtra, GetDoubleExtra, GetDoubleArrayExtra,
// etc, seems like a bad idea.
/**
* Returns the name that will be used to retrieve a result from the activity.
*/
@SimpleProperty(
)
public String ResultName() {
return resultName;
}
/**
* Specifies the name that will be used to retrieve a result from the
* activity.
*/
@DesignerProperty(editorType = PropertyTypeConstants.PROPERTY_TYPE_STRING,
defaultValue = "")
@SimpleProperty
public void ResultName(String resultName) {
this.resultName = resultName.trim();
}
/**
* Returns the result from the activity.
*/
@SimpleProperty(
)
public String Result() {
return result;
}
/**
* Returns the data URI that will be used to start the activity.
*/
@SimpleProperty(
)
public String DataUri() {
return dataUri;
}
/**
* Specifies the data URI that will be used to start the activity.
*/
@DesignerProperty(editorType = PropertyTypeConstants.PROPERTY_TYPE_STRING,
defaultValue = "")
@SimpleProperty
public void DataUri(String dataUri) {
this.dataUri = dataUri.trim();
}
/**
* Returns the MIME type to pass to the activity.
*/
@SimpleProperty(
)
public String DataType() {
return dataType;
}
/**
* Specifies the MIME type to pass to the activity.
*/
@DesignerProperty(editorType = PropertyTypeConstants.PROPERTY_TYPE_STRING,
defaultValue = "")
@SimpleProperty
public void DataType(String dataType) {
this.dataType = dataType.trim();
}
/**
* Returns the package part of the specific component that will be started.
*/
@SimpleProperty(
)
public String ActivityPackage() {
return activityPackage;
}
/**
* Specifies the package part of the specific component that will be started.
*/
@DesignerProperty(editorType = PropertyTypeConstants.PROPERTY_TYPE_STRING,
defaultValue = "")
@SimpleProperty
public void ActivityPackage(String activityPackage) {
this.activityPackage = activityPackage.trim();
}
/**
* Returns the class part of the specific component that will be started.
*/
@SimpleProperty(
)
public String ActivityClass() {
return activityClass;
}
/**
* Specifies the class part of the specific component that will be started.
*/
@DesignerProperty(editorType = PropertyTypeConstants.PROPERTY_TYPE_STRING,
defaultValue = "")
@SimpleProperty
public void ActivityClass(String activityClass) {
this.activityClass = activityClass.trim();
}
/**
* Event raised after this `ActivityStarter` returns.
* @param result The result returned by the activity
*/
@SimpleEvent(description = "Event raised after this ActivityStarter returns.")
public void AfterActivity(String result) {
EventDispatcher.dispatchEvent(this, "AfterActivity", result);
}
/**
* Event raised if this `ActivityStarter returns because the activity was canceled.
*/
@SimpleEvent(description =
"Event raised if this ActivityStarter returns because the activity was canceled.")
public void ActivityCanceled() {
EventDispatcher.dispatchEvent(this, "ActivityCanceled");
}
/**
* Returns the MIME type from the activity.
*/
@SimpleProperty(
)
public String ResultType() {
if (resultIntent != null) {
String resultType = resultIntent.getType();
if (resultType != null) {
return resultType;
}
}
return "";
}
/**
* Returns the URI from the activity.
*/
@SimpleProperty(
)
public String ResultUri() {
if (resultIntent != null) {
String resultUri = resultIntent.getDataString();
if (resultUri != null) {
return resultUri;
}
}
return "";
}
/**
* Specifies the list of key-value pairs that will be passed as extra data to the activity.
*/
@SimpleProperty
public void Extras(YailList pairs) {
for (Object pair : pairs.toArray()) {
boolean isYailList = pair instanceof YailList;
boolean isPair = isYailList ? ((YailList) pair).size() == 2 : false;
if (!isYailList || !isPair) {
throw new YailRuntimeError("Argument to Extras should be a list of pairs",
"ActivityStarter Error");
}
}
extras = pairs;
}
/**
* Returns the list of key-value pairs that will be passed as extra data to the activity.
*/
@SimpleProperty
public YailList Extras() {
return extras;
}
/**
* Returns the name of the activity that corresponds to this `ActivityStarter`,
* or an empty string if no corresponding activity can be found.
*/
@SimpleFunction(description = "Returns the name of the activity that corresponds to this " +
"ActivityStarter, or an empty string if no corresponding activity can be found.")
public String ResolveActivity() {
Intent intent = buildActivityIntent();
PackageManager pm = container.$context().getPackageManager();
ResolveInfo resolveInfo = pm.resolveActivity(intent, 0);
if (resolveInfo != null && resolveInfo.activityInfo != null) {
return resolveInfo.activityInfo.name;
}
return "";
}
/**
* Start the activity corresponding to this `ActivityStarter`.
*/
@SimpleFunction(description = "Start the activity corresponding to this ActivityStarter.")
public void StartActivity() {
resultIntent = null;
result = "";
Intent intent = buildActivityIntent();
if (requestCode == 0) {
// First time, we need to register this as an ActivityResultListener with the Form.
// The Form's onActivityResult method will be called when the activity returns. If we
// register with the Form and then use the requestCode when we start an activity, the Form
// will call our resultReturned method.
}
if (intent == null) {
form.dispatchErrorOccurredEvent(this, "StartActivity",
ErrorMessages.ERROR_ACTIVITY_STARTER_NO_ACTION_INFO);
} else {
try {
container.$context().startActivityForResult(intent, requestCode);
String openAnim = container.$form().OpenScreenAnimation();
AnimationUtil.ApplyOpenScreenAnimation(container.$context(), openAnim);
} catch (ActivityNotFoundException e) {
form.dispatchErrorOccurredEvent(this, "StartActivity",
ErrorMessages.ERROR_ACTIVITY_STARTER_NO_CORRESPONDING_ACTIVITY);
}
}
}
private Intent buildActivityIntent() {
Uri uri = (dataUri.length() != 0) ? Uri.parse(dataUri) : null;
Intent intent = new Intent(action);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (uri != null && dataUri.toLowerCase().startsWith("file://") ) {
Log.d(LOG_TAG, "Using file://");
File file = new File(uri.getPath());
if (file.isFile()) {
Log.d(LOG_TAG, "It's a file");
uri = NougatUtil.getPackageUri(form, file);
intent = new Intent(action);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Log.d(LOG_TAG, "added permissions"); // adb log shows this gets printed
}
}
if (TextUtils.isEmpty(Action())) {
return null;
}
if (dataType.length() != 0) {
if (uri != null) {
intent.setDataAndType(uri, dataType);
} else {
intent.setType(dataType);
}
} else {
intent.setData(uri);
}
if (activityPackage.length() != 0 || activityClass.length() != 0) {
ComponentName component = new ComponentName(activityPackage, activityClass);
intent.setComponent(component);
} else if (Action().equals("android.intent.action.MAIN")) {
return null;
}
if (extraKey.length() != 0 && extraValue.length() != 0) {
Log.i(LOG_TAG, "Adding extra, key = " + extraKey + " value = " + extraValue);
intent.putExtra(extraKey, extraValue);
}
// If the extra value is a string, put it to the intent. If the extra value is a list
// of strings, convert it to a java list and put that to the intent.
for (Object extra : extras.toArray()) {
YailList castExtra = (YailList) extra;
String key = castExtra.getString(0);
Object value = castExtra.getObject(1);
Log.i(LOG_TAG, "Adding extra, key = " + key + " value = " + value);
if ((key.length() != 0)) {
if (value instanceof YailList) {
Log.i(LOG_TAG, "Adding extra list, key = " + key + " value = " + value);
intent.putExtra(key, ((YailList) value).toStringArray());
}
else {
String stringValue = castExtra.getString(1);
Log.i(LOG_TAG, "Adding extra string, key = " + key + " value = " + stringValue);
intent.putExtra(key, stringValue);
}
};
};
return intent;
}
@SimpleEvent(description = "The ActivityError event is no longer used. " +
"Please use the Screen.ErrorOccurred event instead."
)
public void ActivityError(String message) {
}
// Deleteable implementation
}