【问题标题】:why my app shortcut is created twice when my app is downloaded and installed by Google Play为什么 Google Play 下载并安装我的应用程序时,我的应用程序快捷方式会创建两次
【发布时间】:2014-01-04 05:16:17
【问题描述】:

我们遇到了一个奇怪的问题。我们的应用程序已经上传到 Google Play。当我从 Google Play 下载我们的应用程序时,我发现为我们的应用程序创建了 2 个快捷方式。一个是在 Google Play 下载和安装我们的应用程序期间创建的。当我点击在 Google Play 中运行我们的应用程序时,我们的启动屏幕活动将启动,这将创建另一个快捷方式(我们的代码会检查快捷方式是否已创建)。

现在两个快捷方式都存在并且作用不同。如果我从第一个快捷方式启动我的应用程序,并在屏幕中输入一些信息,然后返回主屏幕。并再次单击相同的快捷方式,输入的信息仍然存在。但是,如果我在转到主屏幕后单击另一个快捷方式,则启动屏幕会再次显示,所有输入的数据都消失了。如果我看到正在运行的应用程序(按住 Home 键),我只能看到我们的应用程序的一个正在运行的活动。

这是我们创建快捷方式的代码:

    public static void createShortcut(Activity activity, int iconResId,
        int appNameResId) {
    Intent shortcutIntent = new Intent(
            "com.android.launcher.action.INSTALL_SHORTCUT");
    shortcutIntent.putExtra("duplicate", false);
    shortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME,
            activity.getString(appNameResId));
    Parcelable icon = Intent.ShortcutIconResource.fromContext(
            activity.getApplicationContext(), iconResId);
    shortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, icon);
    Intent extraIntent = new Intent(activity.getApplicationContext(),
            activity.getClass());
    extraIntent.setAction("android.intent.action.MAIN");
    extraIntent.addCategory("android.intent.category.LAUNCHER");
    shortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, extraIntent);

    activity.sendBroadcast(shortcutIntent);

}

这是我们正在检查是否已创建重复快捷方式的代码,基本上我们正在检查是否已创建具有我们的应用程序名称的快捷方式,我知道它不是防弹的,因为其他应用程序将使用与我们的应用程序相同的名称就像我看到一对“手电筒”应用程序一样。另一件事是,很明显我们的应用没有检测到从 Google Play 应用创建的快捷方式:

    public static Boolean isShortcutInstalled(Activity activity,
        int appNameResId) {
    final ContentResolver cr = activity.getContentResolver();
    String authorityString = null;
    if (Build.VERSION.SDK_INT >= 8) {
        authorityString = "com.android.launcher2.settings";
    } else {
        authorityString = "com.android.launcher.settings";
    }
    Uri contentUri = Uri.parse("content://" + authorityString
            + "/favorites?notify=true");
    Cursor cursor = cr.query(contentUri, new String[] { "title",
            "iconResource" }, "title=?",
            new String[] { activity.getString(appNameResId) }, null);
    if (cursor != null && cursor.getCount() > 0) {
        return true;
    }
    return false; 
}

顺便说一句,这是关于 SO 的另一个问题:Is it possible to prevent the Google Play app from creating a shortcut of my App on install?,但是它的答案并没有真正完全解决这个问题。

我现在真的很困惑,有人可以在这里解释一下吗?

更新 1(12 月 17 日):

这是 android 清单文件(我替换了一些名称以删除一些敏感信息)。 SplashActivity 是我们应用的入口点。

<?xml version="1.0" encoding="utf-8"?>

<uses-sdk
    android:minSdkVersion="9"
    android:targetSdkVersion="17" />

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
<uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT"/>
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS"/>

<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />

<application
    android:name=".xxApplication"
    android:allowBackup="true"
    android:icon="@drawable/xx_logo"
    android:label="@string/app_label"
    android:theme="@style/xxTheme.Holo" >
    <activity
        android:name="com.xx.xx.android.MainActivity"
        android:screenOrientation="portrait" >
    </activity>
    <activity
        android:name="com.xx.xx.android.TestActivity"
        android:label="TestActivity"
        android:screenOrientation="portrait" >

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

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

        -->
    </activity>
    <activity
        android:name="com.LS.zxing22.android.CaptureActivity"
        android:configChanges="orientation|keyboardHidden"
        android:screenOrientation="portrait"
        android:theme="@style/xxTheme.NoTitleBar"
        android:windowSoftInputMode="stateAlwaysHidden" >
    </activity>
    <activity
        android:name=".ui.EnrollmentActivity"
        android:screenOrientation="portrait"
        android:theme="@style/xxTheme.NoTitleBar" >
    </activity>
    <activity
        android:name=".ui.LoginActivity"
        android:screenOrientation="portrait"
        android:theme="@style/xxTheme.NoTitleBar" >
    </activity>
    <activity
        android:name=".ui.AgreementActivity"
        android:screenOrientation="portrait" >
    </activity>
    <activity
        android:name=".ui.UsagePolicyActivity"
        android:screenOrientation="portrait" >
    </activity>
    <activity
        android:name=".ui.FinishActivity"
        android:screenOrientation="portrait" >
    </activity>
    <activity
        android:name=".ui.MainActivity"
        android:screenOrientation="portrait"
        android:theme="@style/xxTheme.Holo.Menu" >
    </activity>
    <activity
        android:name=".ui.AccessPasswordActivity"
        android:label="@string/activity_label_access_password"
        android:screenOrientation="portrait" >
    </activity>
    <activity
        android:name=".ui.LoginCodeActivity"
        android:label="@string/activity_label_login_code"
        android:screenOrientation="portrait" >
    </activity>
    <activity
        android:name="org.wordpress.passcodelock.PasscodeUnlockActivity"
        android:screenOrientation="portrait"
        android:theme="@style/xxTheme.NoTitleBar" >
    </activity>
    <activity
        android:name="org.wordpress.passcodelock.PasscodePreferencesActivity"
        android:screenOrientation="portrait" >
    </activity>
    <activity
        android:name="org.wordpress.passcodelock.PasscodeManagePasswordActivity"
        android:screenOrientation="portrait"
        android:theme="@style/xxTheme.NoTitleBar" >
    </activity>
    <activity
        android:name=".ui.SplashActivity"
        android:screenOrientation="portrait"
        android:theme="@style/xxTheme.NoTitleBar.Splash" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity
        android:name=".ui.TutorialActivity"
        android:screenOrientation="portrait">
        <intent-filter>
            <action android:name="com.xx.xx.android.ui.TutorialActivity.Action" />

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

    <service
        android:name="com.xx.xx.android.services.xxService"
        android:enabled="true" >
        <intent-filter>
            <action android:name="com.xx.xx.android.services.IxxServiceRemoteInterface" />
        </intent-filter>
    </service>
    <service
        android:name="com.xx.xx.android.services.NetworkIntentService"
        android:enabled="true" >
    </service>
    <service
        android:name="com.xx.xx.android.services.xxAppIntentService"
        android:enabled="true" >
    </service>
    <service
        android:name="com.xx.xx.android.services.DeviceAttributeUploadIntentService"
        android:enabled="true" >
    </service>
    <service
        android:name="com.xx.xx.android.services.HeartbeatIntentService"
        android:enabled="true" >
    </service>
    <service
        android:name="com.xx.xx.android.services.DeviceWipeIntentService"
        android:enabled="true" >
    </service>
</application>

【问题讨论】:

  • 在最近的一次更新中,您是否更改了根活动(ACTION=MAIN 和 CATEGORY=DEFAULT 的活动)的名称(或包名称)?
  • 我们确实更改了包名,使其全部小写以匹配 java 命名约定。所以我在 Google Play 上取消发布了原始应用程序并重新发布了它。但是我在安装新应用程序之前确实卸载了旧应用程序。新应用首次使用该包名称(小写名称)发布到 Google Play
  • 请分享您的清单...
  • @twntee,我只是使用我们的 Android 应用清单文件编辑我的原始帖子。请让我知道这里出了什么问题,非常感谢。

标签: android google-play


【解决方案1】:

因为在您的 Manifest 中,您使用 Main intent 过滤器声明了 SplashActivity

<activity
        android:name=".ui.SplashActivity"
        android:screenOrientation="portrait"
        android:theme="@style/xxTheme.NoTitleBar.Splash" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

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

该意图过滤器在设备的启动器中放置了一个快捷方式。第二个快捷方式是您在运行时创建的快捷方式

【讨论】:

  • 感谢您的回复。很好,我们找到了原因,虽然我有点困惑。显然,我们需要为要启动的第一个活动提供 Main 意图过滤器,这意味着我们不需要那些代码来为我们的应用程序创建快捷方式,只是想知道为什么还有很多示例代码然后创建快捷方式。似乎根本没有必要。另一件事是我没有看到总是为从 Google Play 安装的应用程序创建快捷方式,尽管我可能是错的(我认为他们需要有那个主要意图过滤器)。
  • 因为它取决于您正在运行的启动器。让我们这样说。 Android 启动器就像普通应用一样,打包在 APK 上。他们像另一个应用程序一样倾听意图(即,当您单击 CHROME 上的 IMDB 链接时,它会要求您打开 IMDB 应用程序)。好的,如果用户将它的启动器替换为另一个不在其应用程序抽屉上创建快捷方式的启动器,那么该代码将使您有机会在用户的主页上创建一个图标。显然,大多数人使用在其抽屉上显示图标的启动器
  • 很棒的信息,非常感谢您的洞察力。另一个问题,对于我们的代码,它用于检查是否创建了快捷方式。知道为什么我们找不到 Google Play 创建的快捷方式吗?我认为我们可能会删除代码以创建快捷方式,因此此代码可能与我们的应用程序无关,但我只想在这里了解更多。 :-)
  • 可能代码在 App Drawer 中检测到快捷方式,但在 Home Desktop 中没有检测到,我真的不知道答案,但也许这会对您有所帮助:stackoverflow.com/questions/4668396/…
猜你喜欢
  • 2016-07-07
  • 1970-01-01
  • 2013-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多