7

I try to call an Intent request from my Flutter/Android project. As described, it should be done as follows

Intent intent = ​new ​Intent();
intent.setComponent(​new ​ComponentName(​"sk.co.xxx.yyy"​, "sk.co.xxx.yyy.MainActivity"​));
JSONObject jReq = ​new ​JSONObject();
String sReq=​""​;
jReq.put(​"Amount"​,​<Amount>​); 
jReq.put(​"Operation"​,​<Operation>​);
jReq.put(​"TransactionID"​,<can be generated e.g.getRandom()>); 
sReq = jReq.toString();

if​(sReq.isEmpty())​return​; 
intent.putExtra(​"POS_EMULATOR_EXTRA"​, sReq); try ​{
startActivityForResult(intent, ​<requestCode>​); }

How to implement this code under Flutter? I tried to use android_intent package from flutter.dev but i I get the following error message:

E/MethodChannel#plugins.flutter.io/android_intent(22815): Failed to handle method call
E/MethodChannel#plugins.flutter.io/android_intent(22815): android.content.ActivityNotFoundException: No Activity found to handle Intent 

Thanks for any answers!

my Flutter code, to replace the code above, is:

if (Platform.isAndroid) {
    Map data = {
      "Amount": "$amount",
      "Operation": "$operation"
    };
  AndroidIntent intent = AndroidIntent(
    componentName: "sk.co.xxx.yyy"​,
    data: data.toString()
  );
  await intent.launch();

I see, that "MainActivity" and putExtra(​"POS_EMULATOR_EXTRA" are not in my Flutter code, but i don't now, how i can implement...

  • Android cannot handle requested Activity. App with requested Activity exists on a device? – fartem Jan 18 '21 at 19:37
  • Yes, exists and running... I think, the Flutter code is not the same, as in the code example (MainActivity, putExtra) – Benedek Körtvélyesi Jan 19 '21 at 07:10
  • Plugin print information about activity that system not found? Maybe in logs? If you use [this](https://pub.dev/packages/android_intent) plugin you may find example on plugin page and compare with your code. – fartem Jan 19 '21 at 08:02
  • Thank You! I use this plugin you wrote, but doesen't work... maybe wrong setup or calls... if you compare the sample code and my code above in question, you see that this are not the same i get following error message: E/MethodChannel#intent(13583): Failed to handle method call E/MethodChannel#intent(13583): kotlin.KotlinNullPointerException – Benedek Körtvélyesi Jan 19 '21 at 10:03
  • Did you manage to find a suitable plugin? I am looking for the same thing :D – Gabriel Solomon May 17 '22 at 21:09
  • To handle the incoming intents from external applications, please check the link: https://docs.flutter.dev/get-started/flutter-for/android-devs#how-do-i-handle-incoming-intents-from-external-applications-in-flutter – harsh bangari May 18 '22 at 07:47
  • @harshbangari The problem is, that the `AndroidManifest.xml` there isn't perfectly correct. – Martin Zeitler May 18 '22 at 11:43

3 Answers3

0

The actual answer can be found in the AndroidManifest.xml, because ActivityNotFoundException can be taken fairly literal... and it means that either Java package or class name cannot be resolved.

String packageName = getApplicationContext().getPackageName(); // just for example
String className = packageName + ".SomeActivity";              // just for example
Intent intent = new Intent(Intent.ACTION_MAIN);                // just for example
intent.setComponent(new ComponentName(packageName, className));

try {
   startActivity(intent);
} catch (ActivityNotFoundException e) {
    Log.e(LOG_TAG, e.getMessage());

    // in here one still could perform a fall-back operation
}

The Activity to resolve for also must have android:exported="true" declared.
It's not wrong to use try / catch there, especially when it's not the own package.

The crucial part is the intent-filter element; when this doesn't match, it will not resolve for, no matter if the Activity exists and is exported - this all is based on the way how intent filters work.

Martin Zeitler
  • 1
  • 19
  • 155
  • 216
0

In the Flutter code you wrote, the package argument is missing, and I guess that the data argument should be replaced by arguments

With the snippet below

 AndroidIntent intent = const AndroidIntent(
      package: 'sk.co.xxx.yyy',
      componentName: 'sk.co.xxx.yyy.MainActivity',
      action: 'action_main',
      arguments: {"POS_EMULATOR_EXTRA" : "{ 'yourJsonKey': 'yourJsonValue'"}
 );
 await intent.launch();

You should be good to go.

Just make sure that your MainActivity has the android:exported="true" flag set in the AndroidManifest.xml, and that your datas are correctly formatted (I'm not sure about your data.toString())

FDuhen
  • 4,097
  • 1
  • 15
  • 26
0

For the flutter portion, the original attempt wasn't too far off and most likely not the cause of the error. Here is an updated snippet that should construct the proper intent.

if (Platform.isAndroid) {
  final extras = json.encode({
    "Amount": amount,
    "Operation": operation,
    "TransactionID": transActionId,
  });
  final intent = AndroidIntent(
    action: 'action_view',
    package: 'sk.co.xxx.yyy',
    componentName: 'sk.co.xxx.yyy.MainActivity',
    arguments: {"POS_EMULATOR_EXTRA": extras},
  );
  await intent.launch();
}

The more likely cause is a problem with the destination app's AndroidManifest.xml. The activity must be exported so external applications can launch it, and it must also have an intent-filter that matches your incoming intent. For this example, I am using the action_view which maps to android.intent.action.VIEW since the intent is carrying data that will result in something being shown to the user. You can also use action_main to match with android.intent.action.MAIN if you prefer that instead.

<activity 
  android:name=".MainActivity"
  android:exported="true">
  <intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
  </intent-filter>
</activity>

Dan Harms
  • 4,725
  • 2
  • 18
  • 28