In my attempts to find out how to start a new intent in my app, I've come across several ways of phrasing it.
This syntax returns a runtime error, namely a ActivityNotFound exception
Intent in = new Intent("com.something.something");
Of course my android manifest contains an action within the intent filter:
<activity
android:name=".SecondActivity"
android:label="#string/title_activity_second" >
<intent-filter>
<action android:name="com.something.something" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
This formatting works:
Intent in = new Intent(MainActivity.this, SecondActivity.class);
I also tried the following:
Intent in = new Intent(this, SomeActivity.class);
that was recommended in a book I'm reading. This returns a runtime error, activitynotfound
This one makes Eclipse throw me back and forth between setClass and setClassName infinitely:
Intent in = new Intent().setClass(this, SecondActivity.class);
I'm using it in an onclick method:
ok.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
Intent in = new Intent(MainActivity.this, SecondActivity.class);
startActivity(in);
}
});
}
What's the difference between these and why is only one of them working for me?
Regards
/M
Basic information about Intent resolution
Intents can contain the following basic information:
ACTION
CATEGORY
DATA
COMPONENT
There are 2 ways that Intents are resolved by the system:
Explicit (uses COMPONENT if it is specified)
Implicit (uses ACTION, CATEGORY and DATA to find suitable activity)
If you specify the component (package name and class name) then this is used to explicitly find the activity you have specified and the Intent is sent to that activity. The other Intent data is not used (although it is passed to the called activity in the Intent). This is called "explicit Intent resolution".
If you don't specify the component, then the ACTION, CATEGORY and DATA fields are used to locate one or more activities that advertise (via intent-filter) that they can accept the Intent. This is called "implicit Intent resolution".
To your specific questions
When you do this:
Intent in = new Intent("com.something.something");
You are creating an implicit Intent and setting the ACTION to "com.something.something". If you then call startActivity() with this Intent, you get ActivityNotFoundException because Android cannot find an activity that can accept an Intent with ACTION="com.something.something". The reason is because you have provided an intent-filter with ACTION="com.something.something" and CATEGORY="android.intent.category.LAUNCHER" but you haven't specified the CATEGORY in your Intent (Android automatically adds the CATEGORY "DEFAULT" to an Intent if there isn't any CATEGORY specified when using startActivity()). To make this work you should either
Replace CATEGORY="android.intent.category.LAUNCHER" with CATEGORY="android.intent.category.DEFAULT" or
Add <category android:name="android.intent.category.DEFAULT" />
to the intent-filter for SecondActivity
When you do this:
Intent in = new Intent(MainActivity.this, SecondActivity.class);
You are creating an explicit Intent specifying the component SecondActivity. The signature for this method is Intent(Context packageContext, Class clas). It uses the package name from packageContext and the class name from clas to create an explicit Intent for that component. If you use this constructor inside an Activity, you can just use this as the first parameter, because Activity extends Context. If you use this constructor from another class (like an OnClickListener) you need to specify MyActivity.this as the first parameter to pass the instance of the Activity and not of the OnClickListener (because OnClickListener does not extend Context).
When you do this:
Intent in = new Intent().setClass(this, SecondActivity.class);
you are creating an explicit Intent as above. This is exactly the same as using:
Intent in = new Intent(this, SecondActivity.class);
You can't do this inside an OnClickListener because the first parameter needs to be a Context (or a class that extends Context, like Activity).
If you want to create an explicit Intent you can also use this:
Intent in = new Intent().setClassName("com.something", "com.something.SecondActivity");
This creates an explicit intent, but you don't need a Context for this. You can just pass the package name and the class name as Strings (if you know them).
For more information about Intent resolution, see:
http://developer.android.com/guide/components/intents-filters.html
http://developer.android.com/reference/android/content/Intent.html
http://developer.android.com/reference/android/content/IntentFilter.html
Please note, when you use "this" key word in "Intent in = new Intent(this, SomeActivity.class); " make sure you are not in a sub class of MainActivity this can set the wrong Activity as part of the Explicit intent Component.strong text
Related
I have 5 or so activities in Android (2 of them have been shown below), which share a common Navigation Drawer. If I log in into some account from the Navigation Drawer, after successful log in, the activity which was previously showing needs to be loaded. Is it possible to send activity context through intent?
FirstActivity.java
Intent intent1 = new Intent(FirstActivity.this, Login.class);
intent1.putExtra("activity", "FirstActivity");
startActivity(intent1);
finish();
SecondActivity.java
Intent intent2 = new Intent(SecondActivity.this, Login.class);
intent2.putExtra("activity", "SecondActivity");
startActivity(intent2);
finish();
When finding the name of the activity to return in log in activity, after successful log in.
Login.java
Intent intent3 = getIntent();
String activity = intent3.getStringExtra("activity");
...
Intent intent4 = new Intent(Login.this, Class.forName(activity));
startActivity(intent4);
finish();
returns the following error message:
W/System.err: java.lang.ClassNotFoundException: Home
at java.lang.Class.classForName(Native Method)
at java.lang.Class.forName(Class.java:453)
Does anyone know how to fix it up?
Making use of intent1.putExtra("activity", String.valueOf(FirstActivity.this)); also does not work out either, it says that com.example.nativeapp.FirstActivity#6a7640 is an invalid class name.
Should I convert the activity context to Serializable or Parcelable or even CharSequence when I try to send those variable values through intent? Activity or AppCompatActivity does not seem to inherit Serializable or Parcelable for that to work out it seems. CharSequence does not seem to make much difference from making use of String.
I know that I can create my own class to store global variables and activity contexts and my activity can inherit from that but since my activity already inherits NavigationDrawer, my activity cannot inherit a second class. Can I declare that as an interface and inherit an interface to access global variable values from interface? Getter and setter methods, for sure cannot work out in an interface, since no implementation of functions and no declaration of variable values are allowed in an interface.
One of the reasons why I have been considering to decide to make use of a central superclass for storing variable values and changing them from subclasses whenever that I am trying to move from one activity to another is that activity contexts like this, I am not sure how to pass them through intents. That intent, which should also be able to pass on within the other central global variables of the mobile application from one activity class to another. The central superclass, such as the NavigationDrawer which is an excellent candidate since all of my Android activity classes inherit from it would be best to use if all central global variables are stored in it and they are changed from subclasses whenever that I am trying to move from one activity to another.
How do I go about it?
you are trying to remember the last activity and then starting next specific activity.
This is the way to do it
change this
Intent intent = new Intent(Login.this, Class.forName(activity));
startActivity(intent);
finish();
to this-
Intent intent = getIntent();
String lastActivity = intent.getStringExtra("activity"); // lastActivity
if (lastActivity.equalsIgnoreCase("FirstActivity")) {
Intent intent = new Intent(Login.this, FirstActivity.class);
startActivity(intent);
finish();
} else if (lastActivity.equalsIgnoreCase("SecondActivity")) {
Intent intent = new Intent(Login.this, SecondActivity.class);
startActivity(intent);
finish();
}
create common method to optimize your code
You need to provide the fully qualified class name. Instead of "FirstActivity" you need to pass "my.fully.qualified.class.name.FirstActivity" where you provide the fully qualified class name.
How can i launch an AndroidAnnotations Activity_ inside of an App (main)
since external Activity (another App).
this is my current code:
Intent codeScannerActivity = new Intent(PACKAGE, CODE_SCANNER_ACTIVITY);
codeScannerActivity.putExtra("codeScannerType", CameraUtils.CODE_SCANNER_SINGLE);
startActivityForResult(codeScannerActivity, Core.ActivityResult.RequestCode.CODE_SCANNER);
where PACKAGE = "main.app.package"
and CODE_SCANNER_ACTIVITY = PACKAGE + ".activity.MyActivity_"
but logs throws:
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=main.app.package dat=main.app.package.activity.MyActivity_ (has extras) }
Activity is defined in the Manifest's Main App with the Class "etc.MyActivity_".
You are constructing the Intent incorrectly. For the constructor you are using, the first parameter is interpreted as an "action" and the second as a URI. The error says that there is no activity which can respond to the action "main.app.package" and the URI "main.app.package.activity.MyActivity_".
To fix the problem, first read Starting Another Activity and the Intent javadocs from the Android Developer site. Especially look at the documentation for the available constructors. There might be one more appropriate for your purposes than the one you are trying to use. The Intent documentation has a list of standard Activity actions. If you want to start a specific activity, you should use Intent (Context packageContext, Class<?> cls):
Intent intent = new Intent(this, main.app.package.activity.MyActivity_.class);
I was creating wrong the Intent, this is the right way:
Intent codeScannerActivity = new Intent();
codeScannerActivity.setComponent(new ComponentName(PACKAGE, CODE_SCANNER_ACTIVITY));
codeScannerActivity.putExtra("codeScannerType", CameraUtils.CODE_SCANNER_SINGLE);
startActivityForResult(codeScannerActivity, Core.ActivityResult.RequestCode.CODE_SCANNER);
In fear of being that guy that asks the question that has been asked already.....*I have looked through the various solutions to this problem, and none seem to solve my problem.
I simply have a button that I would like to start a map activity.
Below is the activity:
public void OnclickButtonListener() {
button_map = (Button)findViewById(R.id.button);
button_map.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent mapintent = new Intent("mf.tutorial.MapsActivity");
startActivity(mapintent);
}
});
and the intent being handled in my manifest file:
<activity
android:name=".MapsActivity"
android:label="#string/title_activity_maps">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
The error returned looks like this:
ActivityNotFoundException: No Activity found to handle Intent { act=mf.tutorial.MapsActivity }
Any help is really appreciated as it has taken me ages to get this far and this is just the latest stumbling block. I would be happy to provide any other parts of the code that might be relevant for a solution!
Thank you very much!
I'm assuming MapsActivity is an activity in your apk? In that case, you would use Intent intent = new Intent(context, MapsActivity.class); The version of Intent you used is for running an activity that has an intent filter for a specific action. Usually used to access system apps like the camera app or the dialer.
When you try to launch your Activity, you do this:
Intent mapintent = new Intent("mf.tutorial.MapsActivity");
This creates an Intent and sets the ACTION in that Intent to "mf.tutorial.MapsActivity".
When you call startActivity(), Android tries to find an Activity in an installed application that knows how to deal with the ACTION "mf.tutorial.MapsActivity". There aren't any, so you get the ActivityNotFoundException.
What you are want to do is to launch the Activity by explicit COMPONENT, and NOT by implicit ACTION. Do that like this:
Intent mapintent = new Intent(context, MapsActivity.class);
startActivity(mapintent);
Using the 2-argument constructor allows you to set the COMPONENT (in this case, MapsActivity) explicitly. The parameter context should be a reference to the calling Activity.
I am trying to follow the lesson here and now im stuck on "Building an Intent". I am quite confused for how to make this Intent and where to paste it. Can someone show me the step by step process on this tutorial? I am getting massive headaches now. Please I want to learn to do this.
Build an Intent
An Intent is an object that provides runtime binding between separate
components (such as two activities). The Intent represents an app’s
"intent to do something." You can use intents for a wide variety of
tasks, but most often they’re used to start another activity.
Inside the sendMessage() method, create an Intent to start an activity
called DisplayMessageActivity:
Intent intent = new Intent(this, DisplayMessageActivity.class); The
constructor used here takes two parameters:
A Context as its first parameter (this is used because the Activity
class is a subclass of Context) The Class of the app component to
which the system should deliver the Intent (in this case, the activity
that should be started)
As the tutorial says, you need to add the line of code that creates an new instance of the Intent class. You will use this instance later to tell the OS to launch another activity or a service. In this particular example, the Intent you are building will direct the OS to launch the DisplayMessageActivity.
To do this step properly, you need to modify the sendMessage method that you have added in the previous step of the tutorial. The final method should look something like this:
/** Called when the user clicks the Send button */
public void sendMessage(View view) {
Intent intent = new Intent(this, DisplayMessageActivity.class);
EditText editText = (EditText) findViewById(R.id.edit_message);
String message = editText.getText().toString();
intent.putExtra(EXTRA_MESSAGE, message);
}
After creating the Intent, the code will take the content of the editText control in the current activity, assign it to the message variable, and then add it as an additional parameter to the intent, so that the target DisplayMessageActivity activity can do something with it.
Don't worry about the DisplayMessageActivity yet. It will be added in a later step.
How do i create Intent and to where to put the codes?
You want to open the activity using intent then you can write your code in this method.
/** Called when the user clicks the Send button */
public void sendMessage(View view) {
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
startActivity(intent);
}
What is the difference between explicit and implicit activity call in android? If you explain the answer with a simple example will be good.
For example:
implicit activity call
In intent filter you create action for you activity, so other app can call your activity via this action as following:
<activity android:name=".BrowserActivitiy" android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http"/>
</intent-filter>
</activity>
And the other way to call implicit Intent is below:
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.example.com"));
startActivity(intent);
Explicit activity call
You make a call that indicate exactly which activity class:
Intent intent = new Intent(this, ActivityABC.class);
intent.putExtra("Value", "This value for ActivityABC");
startActivity(intent);
Hope this help you understand more about Explicit and implicit activity call in android.
You can get more detail about Android Intent here
Explicit Intents are used to call a specific component. When you know which component you want to launch and you do not want to give the user free control over which component to use.For example, you have an application that has 2 activities. Activity A and activity B. You want to launch activity B from activity A. In this case you define an explicit intent targeting activityB and then use it to directly call it.
Implicit Intents are used when you have an idea of what you want to do, but you do not know which component should be launched. Or if you want to give the user an option to choose between a list of components to use. If these Intents are send to the Android system it searches for all components which are registered for the specific action and the data type. If only one component is found, Android starts the component directly. For example, you have an application that uses the camera to take photos. One of the features of your application is that you give the user the possibility to send the photos he has taken. You do not know what kind of application the user has that can send photos, and you also want to give the user an option to choose which external application to use if he has more than one. In this case you would not use an explicit intent. Instead you should use an implicit intent that has its action set to ACTION_SEND and its data extra set to the URI of the photo.
An explicit intent is always delivered to its target, no matter what it contains; the filter is not consulted. But an implicit intent is delivered to a component only if it can pass through one of the component's filters
Every time I get confused among these in either interview. So, I have summarised it like this, may it help someone to keep this difference in mind.
Summary:
In Implicit Intents, the user implicitly tells the system WHAT should be done, without specifying who should do.
In Explicit Intents, the user explicitly tells the system WHOM to be triggered for whatever the work is.
See Intent Resolution here
http://developer.android.com/guide/topics/intents/intents-filters.html
Explicit intents (activities) refer to a specific class, and in general, are only available to your packages. Implicit intents refer to intent filters where apps publicly announce that they can handle certain types of data or can provide specific services, e.g. send an email. With implicit intents, the users chooses which activity (typically a package) to use to handle the intent or if a default handler is set, it is launched.
When to use which?
Explicit intent: When you know which component can handle your request. So you explicitly mention that component name in the intent.
Intent i = new Intent(context,DetailActivity.class); // DetailActivity.class is the component name
startActivity(i);
Implicit intent: When you don't know which application can handle your request then you mention the action in intent and let the OS decide which application/s is/are suitable for your task.
Example: Play music
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(file);
startActivity(intent);
How OS decides?
When there is implicit call with an intent then OS takes out the action and then it matches with all the intent-filters of all the registered activities of all application using PackageManager and then populates the result as a list. It is called intent resolution
So there is a possibility that no application is available in your device which can handle your request. In that case, you will get NullPointer Exception.
So a safer way to call implicit intent would be this
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(file);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
There are two types of intents:
Explicit Intent:
While creating an Intent object when we explicitly specify and pass on the target component name directly in the intent, it’s an explicit intent.
Implicit Intent:
In this case we delegate the task of evaluating the registered components (registration is usually done using intent filters that we’ll cover later) to Android based on the intent data and the intended action (like send an email, capture a photo, pin location on a map, etc.) that we pass. So Android will automatically fire up the component from the same app or some other app that can handle the intent message/job. The idea in this case is that, let’s say we have to pin a location on a map, for that we don’t have to code our own activity to handle that. Instead just pass on the location data to an app like Google maps that can do the job on our app’s behalf.
source : http://codetheory.in/android-intents/
Implicit intent doesn't specify the component. Intent provides the information of a component
Intent intent=new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.google.com"));
startActivity(intent);
whereas,
Explicit intent specify the component. The intent provides information about the class.
Intent i = new Intent(this, ClassB.class);
startActivity(i);