Android intent syntax

2019-04-12 09:35发布

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

1条回答
叛逆
2楼-- · 2019-04-12 10:38

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:

查看更多
登录 后发表回答