Android中的隐式意图与显式意图(startActivity(intent)崩溃)

7

我很新奇。使用startActivity(intent)时遇到了问题。

这是清单文件:

<activity
        android:name="com.example.counter.Splash"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <activity
        android:name="com.example.counter.MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>

以下是代码:

 public class Splash extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);

    setContentView(R.layout.splash);

    Thread timer = new Thread(){
        public void run()
        {
            try
            {
                sleep(5000);

            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
            finally
            {

                Intent i=new Intent ("com.example.counter.MainActivity");
                startActivity(i);
            }
        }
    };

    timer.start();

}

我希望展示启动画面5秒钟,然后显示主界面。日志错误:!https://www.dropbox.com/s/kg7xyp6h4b95itq/Screenshot%202014-02-08%2016.57.36.png

请查看不同的Intent构造函数。您正在尝试使用一个没有存在的操作的Intent进行启动,因此出现了错误。请改用Intent(android.content.Context, java.lang.Class<?>)。 - coderplus
6个回答

15

你想要做的事情有两种方法:

  1. 使用隐式 Intent
  2. 使用显式 Intent

参考意图类型

  1. 隐式 Intent

AndroidManifest.xml 中为你的 Activity 声明 Intent Filters,这样 Android 系统就会了解你的组件(在本例中为 MainActivity)可以处理哪种类型的 Intents

<activity
        android:name="com.example.counter.MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="com.example.counter.MainAction" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
<activity>

现在,您将能够使用相同的Intent启动您的Activity

Intent i=new Intent ("com.example.counter.MainAction");
startActivity(i);

当你不确定应该启动哪个Activity,并且希望Android系统决定要启动哪个组件时,你可以使用隐式Intent。如果系统找到了多个能够处理你的Intent的组件,它将允许用户进行选择。

注意:有可能没有任何应用程序能够处理你的intent。在这种情况下,当你调用startActivity()时,你的应用程序将会崩溃。为了避免这种情况,在调用startActivity()之前,你应该先验证系统中至少有一个已经注册的应用程序可以处理该intent。可以在intent对象上使用resolveActivity()来实现。

  1. 显式Intent

在你的情况下,你应该使用显式Intent,因为你已经知道要启动哪个Activity。所以,通过传递上下文和你想要启动的组件(Activity)类来创建一个Intent

Intent i=new Intent (this,MainActivity.class);
startActivity(i);

3

你需要引用你想要启动的class。所以你需要像这样做:

Intent newAct = new Intent(this, Splash.class);
startActivity(newAct);

您传递的是一个未被理解为类名的Action

1
"com.example.counter.MainActivity" 是一个操作(Action),而不仅仅是一个字符串。 - ρяσѕρєя K
没错!我修改了我的回答。谢谢。 - nKn
但是存在一个公共构造函数 Intent(string action)。 - user3035944
据我理解,您不想在这里放置一个“action”。您想要实例化一个表示Activity的类。因此,您需要使用我提供的代码。 - nKn

1
我猜测,Splash 是你的启动 Activity,在你的清单文件中进行以下更改:
<activity
    android:name="com.example.counter.Splash"
    android:label="@string/app_name" >
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

<activity
    android:name="com.example.counter.MainActivity"
    android:label="@string/app_name" >
</activity>

让您的活动这样进行:
public class Splash extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.splash);

        /*Splach screen that display for 5 seconds when app start*/
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                Intent i = new Intent(Splash.this, MainActivity.class);
                startActivity(i);
                finish();
            }
        }, 5000);

    }

}

我希望现在这应该解决了你的问题。


如果处理不当,这可能会导致巨大的内存泄漏。我建议阅读此内容以了解如何在没有内存泄漏风险的情况下获取“Context”:https://dev59.com/uWw05IYBdhLWcg3wmC6_ - nKn
还有一个错误。在第一条指令中,单词“this”给我带来了这个问题:“类型不匹配:无法从new Thread(){}转换为Context”。 - user3035944
请查看我在描述中放置的链接。 - user3035944

1

我认为您应该能够使用(隐式意图):

Intent i=new Intent ("com.example.counter.MainActivity");

没有理由将其更改为(显式意图):

startActivity(new Intent(mContext, MainActivity.class));

但是您需要更改MainActivity中的intent filter中的action

<action android:name="android.intent.action.MAIN" />

至:

<action android:name="com.example.counter.MainActivity"/>

嘿,我没有找到是否存在任何类似 <action android:name="com.example.counter.MainActivity"/> 的操作。 - Chintan Soni
Intent i = new Intent(String action).意图 i = 新的意图(字符串操作) - Ali
有改变的原因:安全问题。例如,在这种情况下,竞争应用程序也可以提供“com.example.counter.MainActivity”意图,并且每次打开您的应用程序时,用户都会被要求选择他们想要选择的提供者。隐式意图仅用于应用程序之间的服务(例如文档查看器)或在您的应用程序系列中与其他应用程序的转换(通过权限来保护它们,以防止未关联的应用程序访问,除非您希望将意图作为您与世界的API合同的一部分)。 - Theodore Murdock

0
我认为最好使用Handler,将此代码放在启动页Activity的onCreate方法中。
new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                Intent intent = new Intent(getApplicationContext(), MainActivity.class);
                startActivity(intent);
                finish();
            }
        }, 1500); 

如果你想要打开它一次,最好使用SharedPreferences。


0

你需要在清单文件中声明一个活动

像这样:

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name=".FirstActivity"
        android:label="@string/title_activity_main" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activty
        android:name="com.example.counter.MainActivity"/>
</application>

希望能有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接