I am looking to start an activity in my app using a custom action. I have found a few answers but everything I try it throws java.lang.RuntimeException saying No Activity found to handle Intent { act=com.example.foo.bar.YOUR_ACTION }.
This is the activity in my manifest file:
<activity
android:name=".FeedbackActivity" >
<intent-filter>
<action android:name="com.example.foo.bar.YOUR_ACTION" />
</intent-filter>
</activity>
And this is how I'm starting the activity:
Intent intent = new Intent("com.example.foo.bar.YOUR_ACTION");
startActivity(intent);
Any help would be greatly appreciated.
I think what you need is to add a default category to your intent-filter,
eg.
<activity
android:name=".FeedbackActivity" >
<intent-filter>
<action android:name="com.example.foo.bar.YOUR_ACTION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
see this answer for more info.
I think you are creating your intent wrong. Try like this:
String CUSTOM_ACTION = "com.example.foo.bar.YOUR_ACTION";
//Intent i = new Intent(this, FeedBackActivity.class); // <--- You might need to do it this way.
Intent i = new Intent();
i.setAction(CUSTOM_ACTION);
startActivity(i);
Just add and intent-filter category as Default.
Implicit intent works perfectly and in many cases its better to use a implicit intent with Intent-action to call a service/Activity than using class-name.
Before startActivty() / startService() with proper context you cane use this method 'queryIntentActivities(Intent intent, int flags)' from package manager class.
It helps the ActivityManager (responsible for launching activities) to check whether the Android system is getting any match with you Intent.
If it doesn't it returns a list size 0 or else >0.
By this you can also check if your app is getting the call,and in this case even if your app is not installed / has got some problem, it will not crash but will throw a warning in Log. Users will face no big trouble apart from app not being launched.
(users will never forgive you if tour app crashes).
Hope this will help !!!
Happy Coding. :)
I faced the same problem when trying to launch the activity residing in the dynamic feature module and starting through action String as the Activity is not resolvable by name at compile time.
So I set the action but the activity crashes every time (No Activity found to handle intent bla bla.. ) until I set the correct package name.
Context c = getApplicationContext();// flag would be require Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag
Intent i = new Intent(action_string);
i.setPackage(context.getPackageName());//this did the trick actually
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
In the Manifest : add catrgory default to the intent filters
from google docs:
<category android:name="android.intent.category.DEFAULT"/>
Note: In order to receive implicit intents, you must include the CATEGORY_DEFAULT category in the intent filter. The methods startActivity() and startActivityForResult() treat all intents as if they declared the CATEGORY_DEFAULT category. If you do not declare it in your intent filter, no implicit intents will resolve to your activity.
Related
I have an Android application in Android Studio. And I've added a library into the application. The button, view, and activities are defined in the library. When I click on the button, I need to navigate to the activity defined in the application.
Usually, to navigate to another page, we used the intent, like this:
Intent intent = new Intent(MainActivity.this, Activity.class);
startActivity(intent);
But this is not a sufficient method to call the activity of the application from the library.
The problem is that the library and the application are independent; they have different packages. So the activity in the application cannot be recognized by the library.
How do I handle communication between the library and the application?
The normal way for doing this is to do this:
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.my.package","com.my.package.activity.ActivityName");
startActivity(intent);
This is an explicit reference to an activity within your library. You should ensure that when starting this Activity that you catch the ActivityNotFoundException as this can happen when the Activity does not exist in the system.
Ideally when building this Intent you should insure that you can resolve it by using PackageManager APIs.
However you should try to avoid hardcoding packages, but when it comes to a library, sometimes you don't have a choice.
Also one thing to note is that within the library you need to ensure that the Activity is exported so that you can access it outside of your application.
android:exported
Whether or not the activity can be launched by
components of other applications — "true" if it can be, and "false" if
not. If "false", the activity can be launched only by components of
the same application or applications with the same user ID. The
default value depends on whether the activity contains intent filters.
The absence of any filters means that the activity can be invoked only
by specifying its exact class name. This implies that the activity is
intended only for application-internal use (since others would not
know the class name). So in this case, the default value is "false".
On the other hand, the presence of at least one filter implies that
the activity is intended for external use, so the default value is
"true".
This attribute is not the only way to limit an activity's exposure to
other applications. You can also use a permission to limit the
external entities that can invoke the activity (see the permission
attribute).
Ref
http://developer.android.com/guide/topics/manifest/activity-element.html
Include the activity in AndroidManifest.xml.
To access an activity from any other project the easiest way is to
pass the whole class name (including package, e.g;
"com.myproject.MainActivitiy")
Calling from your library :
Intent intent= new Intent("com.myproject.MainActivitiy");
startActivity(intent);
And in your project manifest declare it like this
<activity
android:name="com.myproject.MainActivitiy"
android:label="#string/app_name" >
<intent-filter>
<action android:name="com.myproject.MainActivitiy" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
In this case, Intent can be used by providing the full class name including the package.
Let us suppose your current Activity class is MainActivity.java with package name com.app.myproject.
And you want to navigate to another Activity with class named Activity.java that is in another package com.app.external.
Include com.app.external.Activity.java in the manifest of your current project/library.
<activity
android:name="com.app.external.Activity"
android:label="#string/title_activity_login"
android:screenOrientation="portrait">
</activity>
And your Intent should be like this -
Intent intent = new Intent(MainActivity.this, com.app.external.Activity.class);
startActivity(intent);
In this case use Implicit Intent
Inside library Activity TESTActivity :
Intent intent = new Intent();
intent.setAction("com.myapp.myimplicit_action");
startActivity(intent);
and here is my manifest file declaration for some activity say 'ImplicitActivity' with the same action
<activity android:name=".ImplicitActivity">
<intent-filter>
<action android:name="com.myapp.myimplicit_action" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
I have 2 projects in Eclipse. When I click on a button in project1, I want it to launch an activity from project2.
how can I do that ?
i tried the following code
Intent intent = new Intent(this,com.project2.tp02.MainActivity.class);
intent.setClassName("com.project2.tp02", "com.project2.tp02.MainActivity.class");
startActivity(intent);
I get an error message telling that first application stopped. How can I lauch it properly without such error?
Thanks in advance to any helper.
I got it work using this :
Intent intent = new Intent();
String pkg ="com.project2.tp02";
String clazz =pkg + ".MainActivity";
intent.setComponent(new ComponentName(pkg, clazz));
startActivity(intent);
I don't understand why that way it works and not previous one, if someone can explain I will be thankfull, but anyway I got my problem solved that way.
This is working code to invoke an activity which is in another project.
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.my.package", "com.my.package.MyClass"));
startActivity(intent);
I think your first code did not work because you provide your current activity as context of invoked activity where it is in another application.
<intent-filter>
<action android:name="com.project2.tp02.MainActivity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
Adding the above lines in the Manifest of your first activity might solve your problem.
It would be interesting what the error message is saying exactly... you do need the intent-filter as described by Swayam on the activity you want to call.
Try
new Intent("com.project2.tp02.MainActivity");
to get the intent, instead of setting the class name.
I have an app that starts an activity that isn't the MainActivity first, but it is possible within the course of the app to start the activity on its own. I would like code that runs when the activity is closed to be able to determine if it should go the front of the application(first run) or if it should go back to the previous Activity on the stack(all other runs). Is it possible to determine how an Activity was started inside of it?
You said:
I would like to determine within the course of the Child
Activity what Parent Activity started the Child. In my case that will
either be the Launcher or the MainActivity.
Unfortunately, there is no way to find out what Activity launched your Activity. This information is not available. However...
You can tell if the launcher started your Activity by checking the Intent for ACTION = MAIN and CATEGORY = LAUNCHER:
Intent intent = getIntent();
if (Intent.ACTION_MAIN.equals(intent.getAction()) && intent.hasCategory(Intent.CATEGORY_LAUNCHER)) {
// started by launcher
}
You can also check if the Activity was launched from the list of recent tasks by checking for Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY like this:
Intent intent = getIntent();
if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) {
// Launched from recent task list
}
If this isn't enough for you, then you can always add an "extra" yourself when launching the child Activity from the parent, so that it can tell what Activity started it. For example:
Intent intent = new Intent(this, ChildActivity.class);
intent.putExtra("startedFromMainActivity", true);
startActivity(intent);
and then in your child Activity you can check like this:
Intent intent = getIntent();
if (intent.hasExtra("startedFromMainActivity") {
// started from MainActivity
}
You can store a value in the intent launching your activity, and once opened read it to adapt your behaviour:
intent.putExtra(key,value);
And on the activity side (in onCreate for eg):
getIntent().getExtra(key,defaultValue);
Default value is what you get if no value is found.
getExtra depends o the type of the data stored, so there is getIntExtra ,booleanExtra ,stringExtra ...
Learn more here
your manifesto file exchange mainactivity DEFAULT...
<activity
android:name="com.example.iiintent.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name="com.example.iiintent.al">
<intent-filter>
<category android:name="android.intent.category.LAUNCHER" />
</activity>
I believe I have read all of the similar questions (of which there are many).
Most of them simply said to make sure the activity is (properly) declared in the application's AndroidManifest.xml (done) and that your requested intent and declared intent filters both contain the default category, Intent.CATEGORY_DEFAULT (done).
I am in the process of moving some activities that were in an application project into a library project (that the application references). They were referenced explicitly (by class name), and I'm now trying to refer to them implicitly (via action name, data mime type, and category). Unfortunately, my attempt to start the activity is generating the exception with the detail message in the subject line.
Here is the activity declaration in the application's androidmanifest.xml (within the application node):
<activity android:name="com.everyscape.android.panoramaui.ESPhotoViewActivity" android:enabled="true" android:exported="true">
<intent-filter>
<action android:name="com.everyscape.android.panoramaui.action.VIEW_WORLDTAG"/>
<data android:mimeType="#string/IMAGE_MIME_TYPE"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
Here's the code that attempts to launch that activity:
Context context = this.getContext();
Intent intent = new Intent(ESViewWorldTagActivity.ACTION_VIEW_WORLDTAG);
intent.addCategory(Intent.CATEGORY_DEFAULT);
Uri uri = Uri.parse(dataURL);
intent.setDataAndType(uri, dataMimeType);
intent.putExtra(ESPhotoViewActivity.EXTRA_WORLDTAG_TITLE, title);
intent.putExtra(ESPhotoViewActivity.EXTRA_WORLDTAG_ID, worldTagId);
intent.putExtra(ESPhotoViewActivity.EXTRA_PANORAMA_ID,panoID);
intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
context.startActivity(intent);
In the past - I started the activity by using an explicit intent.
This is the first time I am using an implicit intent.
I don't want to use an explicit intent - because I want the application to be able to override the activity that is used (and the code to launch the activity is in a library - it is not supposed to be application specific).
Here is the exception that I am getting:
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=com.everyscape.android.panoramaui.action.VIEW_WORLDTAG cat=[android.intent.category.DEFAULT] dat=http://ugc.everyscape.com//WT2/BF/EWW-Q-0A1E.JPG typ=image/* flg=0x8 (has extras) }
How can I diagnose and resolve this exception?
Thanks,
Chuck
I have an implicit intent in a service that sends information to my main activity, as well as to another class. I also now want that intent to launch my main activity. I've looked at the myriad posts related to this, and tried lots of different things--addCategory, setAction(MAIN; the activity's name; you name it, I've tried it...), category.DEFAULT in the manifest, and several other things that either resulted in ActivityNotFoundExceptions (most commonly) or behavior that was otherwise undesirable.
Here's where the intent is set up and the relevant part of the manifest. The receiver for the intent is registered in the main activity.
final String NEW_DOSES = "changed to protect the innocent";
Intent bluetoothBroadcast = new Intent();
several putExtra lines here
bluetoothBroadcast.setAction(NEW_DOSES);
sendBroadcast(bluetoothBroadcast);
<activity
android:name=".AsthmaAppActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Is it possible to get this intent to launch my main activity with relatively minor changes? Thanks in advance.
Yes it is possible but no with sendBroadcast(bluetoothBroadcast); sendBroadcast does not launch an activity. You must use startActivity to achieve this. For example here is what a launcher application will do in order to launch an application:
public static void LaunchApplication(Context cx, String packagename) {
PackageManager pm = cx.getPackageManager();
Intent i = pm.getLaunchIntentForPackage(ai.packageName);
if (i != null) cx.startActivity(i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
You can easily adjust the extras and the data needed in order to launch the activity. For example if your activity is named myActivity then you can go like this:
Intent i = new Intent(cx, myActivity.class);
//Put the extras and the data you want here...
//If you are launching the activity from a receiver component you must use
//i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
cx.startActivity(i);
Hope this helps...