【问题标题】:How do i dynamically choose which activity to launch when opening an app打开应用程序时如何动态选择要启动的活动
【发布时间】:2010-05-05 19:19:45
【问题描述】:

我正在编写一个应用程序,该应用程序要求您在使用之前登录到服务。根据我目前对 android 的理解,当您从清单中的启动器打开时,您必须选择要启动的活动。我不知道我想在编译时启动哪个活动。我希望用户单击该图标,然后检查他们是否已登录,然后根据此决定是启动登录活动还是主应用程序活动。有没有办法做到这一点?

【问题讨论】:

    标签: android android-manifest


    【解决方案1】:

    不,因为您必须运行一些代码,所以无法以声明方式(在清单中)这样说。您必须启动一个活动(在清单中设置),然后让此活动根据用户是否登录来决定通过 Intent 启动第二个活动:

    final Class<? extends Activity> activityClass;
    if(userIsLoggedOn())
        activityClass = LoggedOnActivity.class;
    else
        activityClass = LogInActivity.class;
    
    Intent newActivity = new Intent(context, activityClass);
    context.startActivity(newActivity);
    

    【讨论】:

    • 需要注意的一点是,可以在不显示 UI 的情况下启动 Activity,因此您可以让它看起来像在做您想做的事情...请注意,您的逻辑应该完成相当快,因此用户不会注意到它。只需将以下代码放入 Activity 的清单中:android:theme="@android:style/Theme.NoDisplay"
    • 您是否能检测到您将在启动时与其他时间相比?因为人们可能想根据它是否是发布来进行不同的活动?
    • 这会与层次结构混淆吗?即用户可以按后退按钮并结束此活动吗?
    • @James_Parsons 只需确保您没有在活动的元数据中包含 PARENT_ACTIVITY。
    • 哈哈,Application 类是怎么回事?如果您实现 android.app.Application 的子类,您应该运行代码而不显示 Activity 还是我错了?!
    【解决方案2】:

    还有另一种方法可以使用activity-alias

    1. 在清单中:

      <activity
          android:name=".LoginActivity"
          android:icon="@drawable/ic_launcher_main"
          android:label="Login" >
          <intent-filter>
              <action android:name="android.intent.action.MAIN" />
              <category android:name="android.intent.category.LAUNCHER" />
          </intent-filter>
      </activity>
      
      <activity
          android:name=".MainActivity"
          android:icon="@drawable/ic_launcher_main"
          android:label="MainActivity" >
      </activity>
      
      <activity-alias
          android:name=".AliasActivity"
          android:label="AliasActivity"
          android:enabled="false"
          android:targetActivity=".MainActivity" >
          <intent-filter>
              <action android:name="android.intent.action.MAIN" />
              <category android:name="android.intent.category.LAUNCHER" />
          </intent-filter>
      </activity-alias>
      

      2.登录活动中的某处:

      String s = getApplicationContext().getPackageName();
      ComponentName cm = new ComponentName(s, s+".AliasActivity");
      ComponentName cm2 = new ComponentName(s, s+".Login");
      PackageManager pm = this.getPackageManager();
      pm.setComponentEnabledSetting(cm, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 1);
      pm.setComponentEnabledSetting(cm2, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0);
      

    之后,该应用将被杀死一次,下次启动应用时,MainActivity 将成为启动器。

    【讨论】:

    • 酷!唯一不需要额外活动和在 UI 线程上读取共享首选项的解决方案。您可以使用标志 PackageManager.DONT_KILL_APP 而不是 0 或 1,因此应用程序不会退出。仍然有一个问题阻止我使用它:从 Android Studio 下一次运行失败。 (活动被禁用)
    • 我通过为主要活动添加运行配置来解决此限制。所以这个解决方案效果很好
    • 这个答案似乎应该被接受。
    • 不幸的是,这会破坏某些启动器中的图标,并删除大多数添加到主屏幕的图标快捷方式。
    • 正如伊戈尔所说,看起来不错,但工作不稳定。在某些情况下,启动器图标不起作用。当我更改活动并退出应用程序时,有时会看到“未安装应用程序”吐司。一秒钟后,启动器活动发生了变化。
    【解决方案3】:

    Android Framewowrk提供方法
    public Intent setClassName (String packageName, String className)

    Intent 类的一个,您可以使用它来动态选择使用 String 中类的名称来调用哪个活动。

    这是一个例子

        String packageName = getPackageName(), className=packageName+"subFolder.myActivity";
        Intent i = new Intent();
        i.setClassName(packageName, className);
        startActivity(i); 
    

    https://developer.android.com/reference/android/content/Intent.html#setClassName(java.lang.String,%20java.lang.String)

    【讨论】:

      【解决方案4】:

      正如上面@auval所说,我测试了下面的代码,它做得很好! 起初,AndroidManifest.xml 文件是这样的:

       <activity
           android:name=".LauncherActivity">
          <intent-filter>
              <action android:name="android.intent.action.MAIN"/>
              <category android:name="android.intent.category.LAUNCHER"/>
          </intent-filter>
      </activity>
      
      <activity
          android:name=".MainActivity">
      </activity>
      
      <activity-alias
          android:name=".AliasActivity"
          android:enabled="false"
          android:targetActivity=".MainActivity">
          <intent-filter>
              <action android:name="android.intent.action.MAIN"/>
              <category android:name="android.intent.category.LAUNCHER"/>
          </intent-filter>
      </activity-alias>
      

      其次,你可以把这些代码放在MainActivity.class的某个地方:

      private void changeLauncher() {
               String s = getApplicationContext().getPackageName();
               ComponentName cm = new ComponentName(s, s + ".AliasActivity");
              ComponentName cm2 = new ComponentName(s, s + ".LauncherActivity");
              PackageManager pm = this.getPackageManager();
              pm.setComponentEnabledSetting(cm,
                 PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 
                 PackageManager.DONT_KILL_APP );
              pm.setComponentEnabledSetting(cm2, 
                 PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 
                 PackageManager.DONT_KILL_APP);
               }
      

      现在,当您第一次启动应用程序时,LauncherActivity 将启动,当您退出应用程序时,再次运行应用程序,MainActivity 将启动。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-02-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-05
        • 1970-01-01
        相关资源
        最近更新 更多