我创建了一个测试Activity,它在 Android主屏幕上安装了自己的快捷方式.单击按钮时,Activity应该删除它刚刚创建的相同快捷方式.但是,我所做的一切似乎都没有删除快捷方式.

这是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>

我几乎肯定有一些权限问题,虽然我在互联网上看到其他帖子表明这应该是可能的.

任何意见是极大的赞赏.

谢谢.

解决方法

过时;完全为了历史目的而克服

这个答案发布于2014年,当时描述的方法依赖于大多数Android设备中存在的功能.但是,如Adrian-Costin Țundrea所述,这个功能was removed几年前来自Launcher3,它是Google Now Launcher所基于的AOSP启动器1.提交消息说:

Removing support due to its flacky design. Removing a shortcut
causes a full reload. Also we do not have any concept of owner,so
any app can remove any shortcut.

截至2017年3月,该发射器也支持“谷歌搜索启动器服务”,这意味着制造商可以将某个谷歌库集成到他们自己的自定义发射器中,而不是依靠谷歌提供的标准化发射器.

考虑到每个制造商可以自由地以他们想要的方式实现他们的启动器,并假设其中一些基于Launcher3,很难分辨下面的方法将使用哪些设备,因为Launcher3甚至可以在某些Android 4.1设备上运行,这是oldest devices still in use之间的.

问候!

我刚刚处理了同样的问题,并希望在成功解决之后分享我的经验. tl; dr – 跳到下面的“结论”.

一些背景:

在处理应用程序的“下一版本”时,需要更改默认入口点(即重命名“主要活动”).这是不赞成的,因为从旧版本升级的用户仍然会使用旧的快捷方式,指向错误的位置.为了尽可能避免出现问题,在他们不知情的第一次发射时,旧的捷径将被换成新的捷径.

第1步:设置新的入口点

这是最简单的部分.要声明一个入口点,唯一要做的就是放下以下< action ...>在Manifest中的相应活动声明中标记:

<activity
    android:name="YOUR_PACKAGE_NAME.YOUR_ACTIVITY_NAME"
    android:label="@string/app_name">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
    </intent-filter>
</activity>

在某种意义上,入口点默认是什么,是启动器快捷方式指向它.这就是为什么开发人员通常也会在< intent-filter>中包含它:

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

应该注意的是,在< intent-filter>中具有此功能的每个活动都是如此.将在您的应用程序抽屉中创建一个项目 – 这就是为什么在大多数情况下,您只需要1个实例.

第2步:弄清楚旧捷径如何工作

有了root设备,我可以访问存储启动器/主屏幕/桌面项目的数据库表(see image of what the SQLite entries looks like),它位于:

/data/data/com.android.launcher/databases/launcher.db -> SELECT * FROM favorites`

这是图像中突出显示的条目的更易读的版本:

#Intent;
    action=android.intent.action.MAIN;
    category=android.intent.category.LAUNCHER;
    launchFlags=0x10200000;
    package=gidutz.soft.bluecard;
    component=gidutz.soft.bluecard/.LoadingScreen;
 end

注意0x10200000 – 这在第4步 – 下面的尝试1中解释.

第3步:确定快捷方式卸载程序的期望

UninstallShortcutReceiver.java中的第38-42行告诉我们:

Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
boolean duplicate = data.getBooleanExtra(Launcher.EXTRA_SHORTCUT_DUPLICATE,true);

if (intent != null && name != null) { ... }

意味着“卸载意图”必须同时具有Intent.EXTRA_SHORTCUT_INTENT和Intent.EXTRA_SHORTCUT_NAME,否则它甚至不会考虑执行.

第4步:找到正确的语法

这是一个试错的案例,结局很快.

尝试1:重建意图

Intent oldShortcutIntent = new Intent();
oldShortcutIntent.setAction(Intent.ACTION_MAIN);
oldShortcutIntent.addCategory(Intent.CATEGORY_LAUNCHER);
oldShortcutIntent.addFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED +
                           Intent.FLAG_ACTIVITY_NEW_TASK);
oldShortcutIntent.setPackage("gidutz.soft.bluecard");
oldShortcutIntent.setComponent(new ComponentName("gidutz.soft.bluecard",".LoadingScreen"));
//  The above line is equivalent to:
Intent oldShortcutIntent = new Intent(getApplicationContext(),LoadingScreen.class);
Intent uninstaller = new Intent();
uninstaller.putExtra(Intent.EXTRA_SHORTCUT_INTENT,oldShortcutIntent);
uninstaller.putExtra(Intent.EXTRA_SHORTCUT_NAME,"Blue Card");
uninstaller.setAction("com.android.launcher.action.UNINSTALL_SHORTCUT");
getApplicationContext().sendbroadcast(uninstaller);

结果:图标未删除.
0x10200000实际上是两个参数的总和,如here所述.

尝试2:使用来自viralpatel的as-is代码

Intent shortcutIntent = new Intent(getApplicationContext(),LoadingScreen.class);
shortcutIntent.setAction(Intent.ACTION_MAIN);

Intent addIntent = new Intent();
addIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT,shortcutIntent);
addIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME,"Blue Card");

addIntent.setAction("com.android.launcher.action.UNINSTALL_SHORTCUT");
getApplicationContext().sendbroadcast(addIntent);

结果:图标未删除.

尝试3:“蛮力”

尝试完全按照launcher.db中显示的方式复制粘贴意图:

Intent intent = new Intent();
String oldShortcutUri = "#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;package=gidutz.soft.bluecard;component=gidutz.soft.bluecard/.LoadingScreen;end";
try {
    Intent altShortcutIntent  = Intent.parseUri(oldShortcutUri,0);
    intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT,altShortcutIntent);
    intent.putExtra(Intent.EXTRA_SHORTCUT_NAME,"Blue Card");
} catch (URISyntaxException e) {
}
intent.setAction("com.android.launcher.action.UNINSTALL_SHORTCUT");
getApplicationContext().sendbroadcast(intent);

结果:图标已删除!!

结论

>确保“Icon Uninstaller”意图使用与用于创建要删除的图标完全相同的URI,方法是存储用于创建它的URI,或者从launcher.db获取它.
>等待大约2-3秒,以显示“已删除图标”的吐司.

来源

1)This guide at viralpatel.net

2)Google’s implementation of UninstallShortcutReceiver.java

3)This thread at xdadevelopers

附:

为了模拟和调试Google Play更新(保留旧的快捷方式),我执行了以下操作:

>从商店安装旧版本的应用程序 – 带有“旧快捷方式”的图标自动放在我的屏幕上.
>使用Total Commander备份我的launcher.db.
>通过我的IDE安装新版本(您也可以使用.apk) – “旧快捷方式”现在已经消失.
>打开Total Commander并将其最小化(以便在“ALT-TAB”菜单中提供快捷方式).
>转到设备设置>>应用>> ALL,发现我的发射器(对我来说,因为我在CM11上它是“投石机”)并且Force停止了它.
> ALT-TAB进入Total Commander并恢复数据库.
>单击硬件“主页”按钮以重新启动启动器.
>中提琴!旧的快捷方式现已恢复.

注意1:回顾一下,使用从数据库获取的URI手动创建旧快捷方式可能更容易,而不是通过所有备份和强制停止测试.

注意2:我没有尝试使用此方法删除属于其他应用程序的图标,但它可能只是疯狂到可以工作.

android – 尝试UNINSTALL_SHORTCUT但快捷方式不会消失的更多相关文章

  1. html5 canvas合成海报所遇问题及解决方案总结

    这篇文章主要介绍了html5 canvas合成海报所遇问题及解决方案总结,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. Html5 video标签视频的最佳实践

    这篇文章主要介绍了Html5 video标签视频的最佳实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  3. HTML5在微信内置浏览器下右上角菜单的调整字体导致页面显示错乱的问题

    HTML5在微信内置浏览器下,在右上角菜单的调整字体导致页面显示错乱的问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

  4. ios – containerURLForSecurityApplicationGroupIdentifier:在iPhone和Watch模拟器上给出不同的结果

    我使用默认的XCode模板创建了一个WatchKit应用程序.我向iOSTarget,WatchkitAppTarget和WatchkitAppExtensionTarget添加了应用程序组权利.(这是应用程序组名称:group.com.lombax.fiveminutes)然后,我尝试使用iOSApp和WatchKitExtension访问共享文件夹URL:延期:iOS应用:但是,测试NSURL

  5. Ionic – Splash Screen适用于iOS,但不适用于Android

    我有一个离子应用程序,其中使用CLI命令离子资源生成的启动画面和图标iOS版本与正在渲染的启动画面完美配合,但在Android版本中,只有在加载应用程序时才会显示白屏.我检查了config.xml文件,所有路径看起来都是正确的,生成的图像出现在相应的文件夹中.(我使用了splash.psd模板来生成它们.我错过了什么?这是config.xml文件供参考,我觉得我在这里做错了–解决方法在config.xml中添加以下键:它对我有用!

  6. ios – 无法启动iPhone模拟器

    /Library/Developer/CoreSimulator/Devices/530A44CB-5978-4926-9E91-E9DBD5BFB105/data/Containers/Bundle/Application/07612A5C-659D-4C04-ACD3-D211D2830E17/ProductName.app/ProductName然后,如果您在Xcode构建设置中选择标准体系结构并再次构建和运行,则会产生以下结果:dyld:lazysymbolbindingFailed:Symbol

  7. Xamarin iOS图像在Grid内部重叠

    heyo,所以在Xamarin我有一个使用并在其中包含一对,所有这些都包含在内.这在Xamarin.Android中看起来完全没问题,但是在Xamarin.iOS中,图像与标签重叠.我不确定它的区别是什么–为什么它在Xamarin.Android中看起来不错但在iOS中它的全部都不稳定?

  8. ios – Jenkins无法从项目文件夹运行xcodebuild

    我是Jenkins的新手,但是我尽力用GoogleFu回答这个问题无济于事.我最初是通过手动安装Jenkins遇到了这个问题,但最近使用了OSX安装程序并导致了同样的错误.我猜这与Unix/Linux/OSX权限有关,而不是Jenkins/Xcode,但没有足够的专业知识来确定.编辑项目目录权限设置为775.我也尝试将所有权更改为Jenkins运行的用户.这是我尝试将xcodebuild作为守护程序用户运行时的输出:解决方法确保运行Jenkins的用户具有正确的权限.转到http://[jenkins_s

  9. 在iOS上向后播放HTML5视频

    我试图在iPad上反向播放HTML5视频.HTML5元素包括一个名为playbackRate的属性,它允许以更快或更慢的速率或相反的方式播放视频.根据Apple’sdocumentation,iOS不支持此属性.通过每秒多次设置currentTime属性,可以反复播放,而无需使用playbackRate.这种方法适用于桌面Safari,但似乎在iOS设备上的搜索限制为每秒1次更新–在我的情况下太慢了.有没有办法在iOS设备上向后播放HTML5视频?解决方法iOS6Safari现在支持playbackRat

  10. 在iOS(iPhone / iPad / iPod)上查找所有注册的mime-types / url方案协议(intent filters)

    我是移动网络开发人员,我想测试一些iOS设备,以查看iOS设备可以接受的MIME类型和网址计划.在Android上,我可以安装一个名为PackageExplorer的应用程序,该应用程序列出了所有apks的所有“intentfilters”,并列出了什么文件mime-types(image/png,text/html,text/x-vcard)和url方案像geo:,tel:,sms:,mailt

随机推荐

  1. bluetooth-lowenergy – Altbeacon库无法在Android 5.0上运行

    昨天我在Nexus4上获得了Android5.0的更新,并且altbeacon库停止了检测信标.似乎在监视和测距时,didEnterRegion和didRangeBeaconsInRegion都没有被调用.即使RadiusNetworks的Locate应用程序现在表现不同,一旦检测到信标的值,它们就不再得到更新,并且通常看起来好像信标超出了范围.我注意到的一点是,现在在logcat中出现以下行“B

  2. android – react-native动态更改响应者

    我正在使用react-native进行Android开发.我有一个视图,如果用户长按,我想显示一个可以拖动的动画视图.我可以使用PanResponder实现这一点,它工作正常.但我想要做的是当用户长按时,用户应该能够继续相同的触摸/按下并拖动新显示的Animated.View.如果您熟悉Google云端硬盘应用,则它具有类似的功能.当用户长按列表中的任何项目时,它会显示可拖动的项目.用户可以直接拖

  3. android – 是否有可能通过使用与最初使用的证书不同的证书对其进行签名来发布更新的应用程序

    是否可以通过使用与最初使用的证书不同的证书进行签名来发布Android应用程序的更新?我知道当我们尝试将这样的构建上传到市场时,它通常会给出错误消息.但有没有任何出路,比如将其标记为主要版本,指定市场中的某个地方?解决方法不,你不能这样做.证书是一种工具,可确保您是首次上传应用程序的人.所以总是备份密钥库!

  4. 如何检测Android中是否存在麦克风?

    ..所以我想在让用户访问语音输入功能之前检测麦克风是否存在.如何检测设备上是否有麦克风.谢谢.解决方法AndroidAPI参考:hasSystemFeature

  5. Android – 调用GONE然后VISIBLE使视图显示在错误的位置

    我有两个视图,A和B,视图A在视图B上方.当我以编程方式将视图A设置为GONE时,它将消失,并且它正下方的视图将转到视图A的位置.但是,当我再次将相同的视图设置为VISIBLE时,它会在视图B上显示.我不希望这样.我希望视图B回到原来的位置,这是我认为会发生的事情.我怎样才能做到这一点?编辑–代码}这里是XML:解决方法您可以尝试将两个视图放在RelativeLayout中并相对于彼此设置它们的位置.

  6. android – 获得一首歌的流派

    我如何阅读与歌曲相关的流派?我可以读这首歌,但是如何抓住这首歌的流派,它存放在哪里?解决方法检查此代码:

  7. android – 使用textShadow折叠工具栏

    我有一个折叠工具栏的问题,在展开状态我想在文本下面有一个模糊的阴影,我使用这段代码:用:我可以更改textColor,它可以工作,但阴影不起作用.我为阴影尝试了很多不同的值.是否可以为折叠文本投射阴影?

  8. android – 重用arm共享库

    我已经建立了armarm共享库.我有兴趣重用一个函数.我想调用该函数并获得返回值.有可能做这样的事吗?我没有任何头文件.我试过这个Android.mk,我把libtest.so放在/jni和/libs/armeabi,/lib/armeabi中.此时我的cpp文件编译,但现在是什么?我从objdump知道它的名字编辑:我试图用这个android.mk从hello-jni示例中添加prebuild库:它工作,但libtest.so相同的代码显示以下错误(启动时)libtest.so存在于libhello-j

  9. android – 为NumberPicker捕获键盘’Done’

    我有一个AlertDialog只有一些文本,一个NumberPicker,一个OK和一个取消.(我知道,这个对话框还没有做它应该保留暂停和恢复状态的事情.)我想在软键盘或其他IME上执行“完成”操作来关闭对话框,就像按下了“OK”一样,因为只有一个小部件可以编辑.看起来处理IME“Done”的最佳方法通常是在TextView上使用setonEditorActionListener.但我没有任何Te

  10. android – 想要在调用WebChromeClient#onCreateWindow时知道目标URL

    当我点击一个带有target=“_blank”属性的超链接时,会调用WebChromeClient#onCreateWindow,但我找不到新的窗口将打开的新方法?主页url是我唯一能知道的东西?我想根据目标网址更改应用行为.任何帮助表示赞赏,谢谢!

返回
顶部