尝试 UNINSTALL_SHORTCUT 但快捷方式不会消失
我创建了一个测试活动,它在 Android 主屏幕上安装了它自己的快捷方式。当您单击按钮时,活动应该删除它刚刚创建的相同快捷方式。但是,我似乎没有做任何事情来删除快捷方式。
这是 Java 代码 (ShortcutTest.java):
import java.net.URISyntaxException;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class ShortcutTest extends Activity {
String shortcutUri;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
addShortcut(getBaseContext());
Button button = (Button)findViewById(R.id.Button01);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
removeShortcut(getBaseContext());
finish();
}
});
}
public void addShortcut(Context context) {
Intent shortcutIntent = new Intent();
shortcutIntent.setClassName("com.telespree.android.client", "com.telespree.android.client.ShortcutTest");
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
Intent intent = new Intent();
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "ShortcutTest");
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext(context, R.drawable.icon));
intent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
shortcutUri = intent.toUri(MODE_WORLD_WRITEABLE);
context.sendBroadcast(intent);
}
public void removeShortcut(Context context) {
Intent intent = null;
try {
intent = Intent.parseUri(shortcutUri, 0);
} catch (URISyntaxException e) {
}
intent.setAction("com.android.launcher.permission.UNINSTALL_SHORTCUT");
context.sendBroadcast(intent);
}
}
这是清单:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.telespree.android.client"
android:versionCode="1"
android:versionName="1.0">
<permission
android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
android:protectionLevel="normal"
/>
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".ShortcutTest"
android:label="@string/app_name" android:theme="@android:style/Theme.Translucent">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
<!--
<uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT"/>
-->
<uses-sdk android:minSdkVersion="7" />
</manifest>
我几乎肯定存在某种权限问题,尽管我在 Internet 上看到其他帖子表明这应该是可能的。
非常感谢任何建议。
谢谢。
I created a test Activity that installs a shortcut of itself on the Android Home screen. When you click a button, the Activity is supposed to remove the same shortcut it just created. However, nothing I do seems to delete the shortcut.
Here is the Java code (ShortcutTest.java):
import java.net.URISyntaxException;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class ShortcutTest extends Activity {
String shortcutUri;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
addShortcut(getBaseContext());
Button button = (Button)findViewById(R.id.Button01);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
removeShortcut(getBaseContext());
finish();
}
});
}
public void addShortcut(Context context) {
Intent shortcutIntent = new Intent();
shortcutIntent.setClassName("com.telespree.android.client", "com.telespree.android.client.ShortcutTest");
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
Intent intent = new Intent();
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "ShortcutTest");
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext(context, R.drawable.icon));
intent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
shortcutUri = intent.toUri(MODE_WORLD_WRITEABLE);
context.sendBroadcast(intent);
}
public void removeShortcut(Context context) {
Intent intent = null;
try {
intent = Intent.parseUri(shortcutUri, 0);
} catch (URISyntaxException e) {
}
intent.setAction("com.android.launcher.permission.UNINSTALL_SHORTCUT");
context.sendBroadcast(intent);
}
}
Here is the Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.telespree.android.client"
android:versionCode="1"
android:versionName="1.0">
<permission
android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
android:protectionLevel="normal"
/>
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".ShortcutTest"
android:label="@string/app_name" android:theme="@android:style/Theme.Translucent">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
<!--
<uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT"/>
-->
<uses-sdk android:minSdkVersion="7" />
</manifest>
I'm almost positive there is some kind of permissions problem, though I've seen other posts on the Internet that indicates this should be possible.
Any advice is greatly appreciated.
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
已弃用;仅出于历史目的保留
此答案于 2014 年发布,当时所描述的方法依赖于大多数 Android 设备中存在的功能。但是,正如 Adrian-Costin şundrea 提到的,此功能几年前已从 Launcher3 中删除,Launcher3 是 Google 所依赖的 AOSP 启动器现在启动器基于1。提交消息说:
自 2017 年 3 月起,此启动器也将正在逐步淘汰,取而代之的是“Google 搜索启动器服务”,这意味着制造商可以将某个 Google 库集成到他们自己的自定义启动器中,而不是依赖 Google 提供的标准化启动器。
考虑到每个制造商都可以自由地以他们想要的方式实现他们的启动器,并且假设其中一些基于 Launcher3,很难判断下面的方法适用于哪些设备,因为 Launcher3 甚至可以在某些设备上运行="https://f-droid.org/wiki/page/com.android.launcher3" rel="nofollow noreferrer">Android 4.1 设备,属于 仍在使用的最旧设备。
问候!
我刚刚处理了同样的问题,并想在成功解决后分享我的经验。 tl;dr - 跳到下面的“结论”。
一些背景:
在开发应用程序的“下一个版本”时,需要更改默认入口点(即重命名“Main活动”)。这是令人不悦的,因为从旧版本升级的用户仍然会使用旧的快捷方式,指向错误的位置。为了尽可能避免出现问题,在第一次启动时,在他们不知情的情况下,旧的快捷方式被替换为新的快捷方式。
第 1 步:设置新的入口点
这是最简单的部分。要声明入口点,唯一要做的事情就是将以下
标记放入清单内相应的活动声明中:从某种意义上说,入口点默认是启动器快捷方式指向它。这就是为什么开发人员通常也会将其包含在
中:应该注意的是,每个在其
中包含此内容的活动 <将会在您的应用程序抽屉中创建一个项目 - 这就是为什么在大多数情况下您只需要 1 个实例。步骤 2:弄清楚旧快捷方式是如何工作的
有了 root 设备,我可以访问存储启动器/主屏幕/桌面项目的数据库表 (查看 SQLite 条目的图像) 位于:
这是图像中突出显示的条目的更易读的版本:
请注意
0x10200000
- 这在下面的步骤 4 - 尝试 1 中进行了解释。第 3 步:弄清楚快捷方式卸载程序期望什么
UninstallShortcutReceiver.java
中的第 38-42 行告诉我们:这意味着“卸载意图”必须两者
Intent.EXTRA_SHORTCUT_INTENT
和Intent.EXTRA_SHORTCUT_NAME
否则它甚至不会考虑执行。第四步:找到正确的语法
这是一个尝试错误但结局美好的例子。
尝试 1:重建意图
结果: 图标未删除。
0x10200000
实际上是两个参数的总和,如所解释的尝试 2:使用 Viralpatel 中的原样代码
结果: 图标未删除。
尝试 3:“暴力”
尝试完全按照 launcher.db 中显示的方式复制粘贴意图:
结果:图标已删除!
结论
来源
1) 本指南位于 Viralpatel.net< /a>
2) Google 的 UninstallShortcutReceiver.java 实现
3) xdadevelopers 上的此线程
PS
为了模拟和调试 Google Play 更新(保留旧快捷方式),我执行了以下操作:
注 1:回想起来,使用从数据库获取的 URI 手动创建旧快捷方式可能更容易,而不是经历所有备份和强制停止的考验。
注意2:我还没有尝试使用此方法删除属于其他应用程序的图标,但它可能足够疯狂,可以工作。
DEPRECATED; KEPT SOLELY FOR HISTORICAL PURPOSES
This answer was posted in 2014, when the described method relied on functionality that existed in most Android devices. However, as mentioned by Adrian-Costin Țundrea, this functionality was removed a couple of years ago from Launcher3, which is the AOSP launcher upon which the Google Now Launcher is based1. The commit message said:
As of March 2017, this launcher, too, is being phased out in favor of "Google Search Launcher Services", which means that manufacturers could integrate a certain Google library into their own custom launchers, instead of relying on a standardized launcher provided by Google.
Considering that each manufacturer is free to implement their launcher whichever way they want, and assuming some of them are based off Launcher3, it's difficult to tell which devices the method below will work on, as Launcher3 was made to run even on some Android 4.1 devices, which are among the oldest devices still in use.
Greetings!
I have just dealt with the same exact problem, and would like to share my experience after successfully resolving it. tl;dr - skip to "In Conclusion" below.
Some background:
While working on the "next version" of an app, a need arose to change the default entry point (i.e. to rename the "Main Activity"). This is frowned upon because users who would be upgrading from an old version will still have the old shortcut, pointing to the wrong place. In order to avoid problems as much as possible, on the first launch, unbeknownst to them, the old shortcut was to be replaced with a new one.
Step 1: Setting up a new entry point
This is the easiest part. To declare an entry point the only essential thing to do is to put the following
<action ...>
tag in the appropriate activity declaration inside your Manifest:What makes an entry point default in some sense, is that the launcher shortcut points to it. This is why developers usually also include this in the
<intent-filter>
:It should be noted that every activity that has this in its
<intent-filter>
will create an item in your app drawer - this is why for most cases 1 instance is all you need.Step 2: Figuring out how the old shortcut is working
Having a rooted device, I could access the database table where the launcher/homescreen/desktop items are stored (see image of what the SQLite entries looks like) that's located in:
Here's a more readable version of the highlighted entry from the image:
Note the
0x10200000
- this is explained in Step 4 - Attempt 1 below.Step 3: Figuring out what the Shortcut Uninstaller is expecting
Lines 38-42 in
UninstallShortcutReceiver.java
tell us that:Meaning that the "uninstallation intent" has to have both
Intent.EXTRA_SHORTCUT_INTENT
andIntent.EXTRA_SHORTCUT_NAME
or else it will not even consider executing.Step 4: Finding the Right Syntax
This is a case of trial an error with a happy ending.
Attempt 1: Reconstructing the intent
Result: Icon not removed.
The
0x10200000
is actually a sum of two arguments as explained here.Attempt 2: Using as-is code from viralpatel
Result: Icon not removed.
Attempt 3: "Brute Force"
Trying to copy-paste the intent exactly as it appears in the launcher.db:
Result: Icon removed!!
In Conclusion
launcher.db
.Sources
1) This guide at viralpatel.net
2) Google's implementation of UninstallShortcutReceiver.java
3) This thread at xdadevelopers
P.S.
In order to simulate and debug a Google Play update (which keeps the old shortcut) I did the following:
Note1: In retrospective, it might have been easier to create the old shortcut manually using the URI obtained from the database instead of going through all backing-up and force-stopping ordeal.
Note2: I haven't tried removing icons belonging to other apps using this method, but it might just be crazy enough to work.
虽然 Dev-iL 和 Funt 的两种解决方案都有效,但请注意,它们在 Marshmallow 之前都是如此。在 Android 6.0(具有 Launcher v3)中,Google 由于其安全问题而删除了 UninstallShortcutReceiver(可能是因为它变得明显这里)。所以不要指望它能与 Android 6.0 兼容。希望在未来的版本中,它将以某种形式或另一种形式被阅读。
PS:通常这应该是一个评论,但由于声誉,我不允许发表评论......
While both solutions from Dev-iL and Funt work be advised they do so until Marshmallow. With Android 6.0 (which has Launcher v3) Google has removed the UninstallShortcutReceiver because of its security problems (probably because it became apparent here). So do not expect it to work with Android 6.0. Hopefully in some future release it will be readded in a form or another.
PS: Normally this should be a comment, but I am not allowed to comment because of the reputation...
您需要为
shortcutIntent
设置操作,例如:You need to setAction for
shortcutIntent
like:尝试使用
注意:您不必保存
shortcutUri
即可删除快捷方式。相反,您可以使用如果您想使用
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT,shortcutIntent);
而不是那么您需要每次为
shortcutIntent
设置操作,即在安装时以及卸载时,例如Intent捷径Intent = new Intent(Intent.ACTION_MAIN);
Try to use
Note: You do not have to save
shortcutUri
to remove the shortcut. Instead you can useIf you want to use
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
instead ofthen you need to set action for
shortcutIntent
each time , i.e. while installing as well as while uninstalling e.g.Intent shortcutIntent = new Intent(Intent.ACTION_MAIN);
我花了大约一个小时的时间调试并尝试了 stackoverflow 上的每个示例,但解决方案非常简单。您的代码中有一个拼写错误:您需要使用 com.android.launcher.action.UNINSTALL_SHORTCUT (与清单中的权限相反)
It took me about an hour of debugging and trying out every example on stackoverflow, but the solution was very easy. There's a typo in your code: You need to use com.android.launcher.action.UNINSTALL_SHORTCUT (as opposed to permission, as it is in the Manifest)