Issue:
The Android version of the app will crash when using the UX native trigger <LaunchUri> if the requested activity cannot be found to handle intent.
Debug info from Android:
DEBUG|04-25 13:20:27.820|27664|27664||Instrumentation|checkStartActivityResult :Intent { act=android.intent.action.VIEW dat=purple://company.purple.com }
WARNING|04-25 13:20:27.830|27664|27664||System.err|android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=purple://company.purple.com }
DEBUG|04-25 13:20:27.850|27664|27664||fuseapp|android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=purple://company.purple.com }
INFO|04-25 13:20:27.850|27664|27664||fuseapp|android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=purple://company.purple.com}
INFO|04-25 13:20:27.850|27664|27664||fuseapp|android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=purple://company.purple.com }
WARNING|04-25 13:20:27.850|27664|27664||System.err|java.lang.RuntimeException: android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=purple://company.purple.com }
Debug Output From Fuse:
The txt file had to be zipped as the post went over its word limit, can be downloaded here: Debug Output From Fuse
Expected Outcome:
The Android version of the app should not crash when the UX native trigger <LaunchUri> is triggered when there is no activity found to handle intent. Nothing should happen when triggered (similar to iOS).
To Recreate:
Install below test app on device
Tap on “Open App” button
If requested app is not installed on Android the app will crash
Our current rushed workaround for this is below. I wanted to create a custom TriggerAction such as <LaunchApp Uri="purple://company.purple.com" /> but have not figured out how to do that yet. In the example below the third button will not crash app but the other two will if no intent is found.
A couple of questions:
If you uncomment Launcher.LaunchUri(new Uno.Net.Http.Uri(appPath)); an error will be thrown E3111: 'Uno.Net' does not contain type or namespace 'Http'. Could you be missing a package reference? what would be causing that?
On catch how would you activate the toast? Is my context reference not correct?
How could I turn this into a TriggerAction instead?
We updated our workaround to use a custom TriggerAction which displays an alert (iOS) or toast message (Android) if the app fails to launch (i.e. <LaunchApp Uri="purple://company.purple.com" />).
using Uno;
using Uno.Collections;
using Fuse;
using Fuse.Triggers.Actions;
using Uno.Compiler.ExportTargetInterop;
[ForeignInclude(Language.Java, "com.fuse.Activity", "android.content.Context", "android.content.Intent", "android.net.Uri", "android.widget.Toast")]
public class LaunchApp : TriggerAction
{
String _uri = "";
public String Uri
{
get { return _uri; }
set { _uri = value; }
}
protected override void Perform(Node target)
{
if defined(Android || iOS)
{
// Do Android/iOS Stuff
OpenApp();
} else {
Launcher.LaunchUri(new Uno.Net.Http.Uri(Uri));
}
}
[Foreign(Language.Java)]
public extern(Android) void OpenApp()
@{
try {
Uri uri = Uri.parse(@{LaunchApp:Of(_this).Uri:Get()});
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(uri);
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
Activity.getRootActivity().startActivity(intent);
} catch (Exception e) {
Context context = Activity.getRootActivity();
CharSequence text = "Hello toast!";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
}
@}
[Foreign(Language.ObjC)]
public extern(iOS) void OpenApp()
@{
NSURL *url = [NSURL URLWithString:@{LaunchApp:Of(_this).Uri:Get()}];
if([[UIApplication sharedApplication] openURL:url]) {
NSLog(@"App opened");
} else {
UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"My Alert" message:@"This is an alert." preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {}];
[alert addAction:defaultAction];
[[[UIApplication sharedApplication] keyWindow].rootViewController presentViewController:alert animated:YES completion:nil];
}
@}
}