Android快捷方式解密
Android快捷方式作為Android裝置的殺手锏技能,一直都是非常重要的一個功能,也正是如此,各種流氓App也不斷通過快捷方式霸占着這樣一個使用者入口。
同時,各大國産ROM和Luncher的崛起,讓這個桌面之争變的更加激烈。畢竟大家都隻想使用者用自己的App資源,是以,現在各大App不僅僅是要搶占入口,同時還要和各大ROM鬥智鬥勇。本文将對這個快捷方式進行深度解密,同時給出App适配各種ROM的整合方案。
本文很多地方參考了這位朋友的實作:
https://gist.github.com/waylife/437a3d98a84f245b9582
特此表示感謝!
建立快捷方式之——少林派
所謂少林,是指系統正統的解決方法
天下武功出少林,天下的快捷方式都是Google給的,我們先來看看如何使用Android系統提供的方式來使用Android的快捷方式。
首先大家要知道各種Launcher的差別,原生的Launcher,是兩層結構,桌面是快捷方式,而進去後的App清單是App的Launch Icon;而以小米為首的一幫ROM,參考iOS風格,将Launcher改為了一層,即直接顯示Launch Icon。
權限設定
<!-- 添加快捷方式 -->
<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" />
建立快捷方式
建立快捷方式的Action:
// Action 添加Shortcut
public static final String ACTION_ADD_SHORTCUT = "com.android.launcher.action.INSTALL_SHORTCUT";
通過廣播建立快捷方式:
/**
* 添加快捷方式
*
* @param context context
* @param actionIntent 要啟動的Intent
* @param name name
*/
public static void addShortcut(Context context, Intent actionIntent, String name,
boolean allowRepeat, Bitmap iconBitmap) {
Intent addShortcutIntent = new Intent(ACTION_ADD_SHORTCUT);
// 是否允許重複建立
addShortcutIntent.putExtra("duplicate", allowRepeat);
// 快捷方式的标題
addShortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, name);
// 快捷方式的圖示
addShortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON, iconBitmap);
// 快捷方式的動作
addShortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, actionIntent);
context.sendBroadcast(addShortcutIntent);
}
參數相信大家都能看得懂,隻是有一點需要注意的,duplicate這個屬性,是設定該快捷方式是否允許多次建立的屬性,但是,在很多ROM上都不能成功識别,嗯,這就是我們最開始說的快捷方式亂現象。
删除快捷方式
删除快捷方式的Action:
// Action 移除Shortcut
public static final String ACTION_REMOVE_SHORTCUT = "com.android.launcher.action.UNINSTALL_SHORTCUT";
通過廣播删除快捷方式:
/**
* 移除快捷方式
*
* @param context context
* @param actionIntent 要啟動的Intent
* @param name name
*/
public static void removeShortcut(Context context, Intent actionIntent, String name) {
Intent intent = new Intent(ACTION_REMOVE_SHORTCUT);
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, name);
// intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.putExtra("duplicate", false);
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, actionIntent);
context.sendBroadcast(intent);
}
參數與建立快捷方式的方法擊敗類似,需要注意的是,Intent.EXTRA_SHORTCUT_INTENT,與之前建立快捷方式的Intent必須要是同一個,不然是無法删除快捷方式的。
建立快捷方式之——逍遙派
所謂逍遙派,是指我們從原理來了解如何來适配各種Launcher。
原生的快捷方式添加方法,雖然是官方提供的,但在天國這樣一個怎麼說呢的國家裡,基本是很難使用、适配的,也就是我們最開始說的那些原因。下面我們先從快捷方式的整個生命周期來了解下産生、添加、删除快捷方式的原理,再來思考如何實作多ROM、Launcher的适配。
快捷方式的存儲
快捷方式其實都存儲在Launcher的資料庫中,我們在手機上打開SQLite Editor打開Launcher的資料庫。

我們打開Launcher.db的favorite表,這裡就是我們儲存的快捷方式資料:
幾個主要的字段大家基本一看就懂:title、intent、iconResource、icon,分别對應快捷方式名稱,快捷方式intent,快捷方式圖示來源,快捷方式圖示二進制資料。
快捷方式的建立
了解了快捷方式的存儲原理,我們就可以針對這個資料庫來做文章,所有的快捷方式都可以通過修改這個資料庫來實作,同時還不用太考慮相容性問題。
對于快捷方式的建立,我們依然可以使用系統提供的方法,是以這裡不再多說。
快捷方式的判斷是否存在
前面我們說了,通過duplicate屬性可以區分是否允許建立重複的快捷方式,但是,很多ROM是無法相容到的,是以,這裡我們使用查詢Launcher資料庫的方式來實作。
我們先來看代碼:
/**
* 檢查快捷方式是否存在 <br/>
* <font color=red>注意:</font> 有些手機無法判斷是否已經建立過快捷方式<br/>
* 是以,在建立快捷方式時,請添加<br/>
* shortcutIntent.putExtra("duplicate", false);// 不允許重複建立<br/>
* 最好使用{@link #isShortCutExist(Context, String, Intent)}
* 進行判斷,因為可能有些應用生成的快捷方式名稱是一樣的的<br/>
*/
public static boolean isShortCutExist(Context context, String title) {
boolean result = false;
try {
ContentResolver cr = context.getContentResolver();
Uri uri = getUriFromLauncher(context);
Cursor c = cr.query(uri, new String[]{"title"}, "title=? ", new String[]{title}, null);
if (c != null && c.getCount() > 0) {
result = true;
}
if (c != null && !c.isClosed()) {
c.close();
}
} catch (Exception e) {
result = false;
e.printStackTrace();
}
return result;
}
/**
* 不一定所有的手機都有效,因為國内大部分手機的桌面不是系統原生的<br/>
* 更多請參考{@link #isShortCutExist(Context, String)}<br/>
* 桌面有兩種,系統桌面(ROM自帶)與第三方桌面,一般隻考慮系統自帶<br/>
* 第三方桌面如果沒有實作系統響應的方法是無法判斷的,比如GO桌面<br/>
*/
public static boolean isShortCutExist(Context context, String title, Intent intent) {
boolean result = false;
try {
ContentResolver cr = context.getContentResolver();
Uri uri = getUriFromLauncher(context);
Cursor c = cr.query(uri, new String[]{"title", "intent"}, "title=? and intent=?",
new String[]{title, intent.toUri(0)}, null);
if (c != null && c.getCount() > 0) {
result = true;
}
if (c != null && !c.isClosed()) {
c.close();
}
} catch (Exception ex) {
result = false;
ex.printStackTrace();
}
return result;
}
private static Uri getUriFromLauncher(Context context) {
StringBuilder uriStr = new StringBuilder();
String authority = LauncherUtil.getAuthorityFromPermissionDefault(context);
if (authority == null || authority.trim().equals("")) {
authority = LauncherUtil.getAuthorityFromPermission(context, LauncherUtil.getCurrentLauncherPackageName(context) + ".permission.READ_SETTINGS");
}
uriStr.append("content://");
if (TextUtils.isEmpty(authority)) {
int sdkInt = android.os.Build.VERSION.SDK_INT;
if (sdkInt < 8) { // Android 2.1.x(API 7)以及以下的
uriStr.append("com.android.launcher.settings");
} else if (sdkInt < 19) {// Android 4.4以下
uriStr.append("com.android.launcher2.settings");
} else {// 4.4以及以上
uriStr.append("com.android.launcher3.settings");
}
} else {
uriStr.append(authority);
}
uriStr.append("/favorites?notify=true");
return Uri.parse(uriStr.toString());
}
這裡有兩個重載的isShortCutExist方法,唯一的差別就是最後一個參數——intent,加這個參數的原因,在注釋中已經寫了,更加精确。而getUriFromLauncher方法,是給調用的ContentResolver提供Uri。構造的時候,可以看見,Android的版本話碎片問題,是多麼的嚴重……
這樣在添加快捷方式前,通過這個判斷下,就可以隻添加一個快捷方式了。
為任意PackageName的App添加快捷方式
知道了我們是如何判斷快捷方式是是否存在的,我們就可以通過這種思路來為任意PackageName的App添加快捷方式,代碼如下:
/**
* 為PackageName的App添加快捷方式
*
* @param context context
* @param pkg 待添加快捷方式的應用包名
* @return 傳回true為正常執行完畢
*/
public static boolean addShortcutByPackageName(Context context, String pkg) {
// 快捷方式名
String title = "unknown";
// MainActivity完整名
String mainAct = null;
// 應用圖示辨別
int iconIdentifier = 0;
// 根據包名尋找MainActivity
PackageManager pkgMag = context.getPackageManager();
Intent queryIntent = new Intent(Intent.ACTION_MAIN, null);
queryIntent.addCategory(Intent.CATEGORY_LAUNCHER);// 重要,添加後可以進入直接已經打開的頁面
queryIntent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
queryIntent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY);
List<ResolveInfo> list = pkgMag.queryIntentActivities(queryIntent,
PackageManager.GET_ACTIVITIES);
for (int i = 0; i < list.size(); i++) {
ResolveInfo info = list.get(i);
if (info.activityInfo.packageName.equals(pkg)) {
title = info.loadLabel(pkgMag).toString();
mainAct = info.activityInfo.name;
iconIdentifier = info.activityInfo.applicationInfo.icon;
break;
}
}
if (mainAct == null) {
// 沒有啟動類
return false;
}
Intent shortcut = new Intent(
"com.android.launcher.action.INSTALL_SHORTCUT");
// 快捷方式的名稱
shortcut.putExtra(Intent.EXTRA_SHORTCUT_NAME, title);
// 不允許重複建立
shortcut.putExtra("duplicate", false);
ComponentName comp = new ComponentName(pkg, mainAct);
shortcut.putExtra(Intent.EXTRA_SHORTCUT_INTENT,
queryIntent.setComponent(comp));
// 快捷方式的圖示
Context pkgContext = null;
if (context.getPackageName().equals(pkg)) {
pkgContext = context;
} else {
// 建立第三方應用的上下文環境,為的是能夠根據該應用的圖示辨別符尋找到圖示檔案。
try {
pkgContext = context.createPackageContext(pkg,
Context.CONTEXT_IGNORE_SECURITY
| Context.CONTEXT_INCLUDE_CODE);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
if (pkgContext != null) {
Intent.ShortcutIconResource iconRes = Intent.ShortcutIconResource
.fromContext(pkgContext, iconIdentifier);
shortcut.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconRes);
}
// 發送廣播,讓接收者建立快捷方式
// 需權限<uses-permission
// android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
context.sendBroadcast(shortcut);
return true;
}
建立快捷方式之——星宿派
所謂星宿派,是指我們使用一些Trick來解決多Launcher适配的問題。
由于快捷方式的碎片化非常嚴重,是以,你顧得上這種ROM,顧不上其它ROM。例如,在原生ROM上,你需要使用類似原生的Launcher權限:
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
<uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT" />
但是,在其它ROM上呢,例如華為,你需要這樣的權限:
<uses-permission android:name="com.huawei.launcher3.permission.READ_SETTINGS" />
<uses-permission android:name="com.huawei.launcher3.permission.WRITE_SETTINGS" />
為了程式能夠通用性夠強,理論上我們得為所有不使用原生Launcher權限的Launcher配置權限代碼,是的,你妹聽錯,是所有,隻有通過這種奇技淫巧,才能适配更多的Launcher,這裡貼一部分給大家爽一下:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<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-permission android:name="com.android.launcher.permission.WRITE_SETTINGS" />
<uses-permission android:name="com.android.launcher2.permission.READ_SETTINGS" />
<uses-permission android:name="com.android.launcher2.permission.WRITE_SETTINGS" />
<uses-permission android:name="com.android.launcher3.permission.READ_SETTINGS" />
<uses-permission android:name="com.android.launcher3.permission.WRITE_SETTINGS" />
<uses-permission android:name="org.adw.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="org.adw.launcher.permission.WRITE_SETTINGS" />
<uses-permission android:name="com.htc.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.htc.launcher.permission.WRITE_SETTINGS" />
<uses-permission android:name="com.qihoo360.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.qihoo360.launcher.permission.WRITE_SETTINGS" />
<uses-permission android:name="com.lge.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.lge.launcher.permission.WRITE_SETTINGS" />
<uses-permission android:name="net.qihoo.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="net.qihoo.launcher.permission.WRITE_SETTINGS" />
<uses-permission android:name="org.adwfreak.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="org.adwfreak.launcher.permission.WRITE_SETTINGS" />
<uses-permission android:name="org.adw.launcher_donut.permission.READ_SETTINGS" />
<uses-permission android:name="org.adw.launcher_donut.permission.WRITE_SETTINGS" />
<uses-permission android:name="com.huawei.launcher3.permission.READ_SETTINGS" />
<uses-permission android:name="com.huawei.launcher3.permission.WRITE_SETTINGS" />
<uses-permission android:name="com.fede.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.fede.launcher.permission.WRITE_SETTINGS" />
<uses-permission android:name="com.sec.android.app.twlauncher.settings.READ_SETTINGS" />
<uses-permission android:name="com.sec.android.app.twlauncher.settings.WRITE_SETTINGS" />
<uses-permission android:name="com.anddoes.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.anddoes.launcher.permission.WRITE_SETTINGS" />
<uses-permission android:name="com.tencent.qqlauncher.permission.READ_SETTINGS" />
<uses-permission android:name="com.tencent.qqlauncher.permission.WRITE_SETTINGS" />
<uses-permission android:name="com.huawei.launcher2.permission.READ_SETTINGS" />
<uses-permission android:name="com.huawei.launcher2.permission.WRITE_SETTINGS" />
<uses-permission android:name="com.android.mylauncher.permission.READ_SETTINGS" />
<uses-permission android:name="com.android.mylauncher.permission.WRITE_SETTINGS" />
<uses-permission android:name="com.ebproductions.android.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.ebproductions.android.launcher.permission.WRITE_SETTINGS" />
<uses-permission android:name="com.oppo.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.oppo.launcher.permission.WRITE_SETTINGS" />
<uses-permission android:name="com.miui.mihome2.permission.READ_SETTINGS" />
<uses-permission android:name="com.miui.mihome2.permission.WRITE_SETTINGS" />
<uses-permission android:name="com.huawei.android.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.huawei.android.launcher.permission.WRITE_SETTINGS" />
<uses-permission android:name="telecom.mdesk.permission.READ_SETTINGS" />
<uses-permission android:name="telecom.mdesk.permission.WRITE_SETTINGS" />
<uses-permission android:name="dianxin.permission.ACCESS_LAUNCHER_DATA" />
這時候大家肯定要問了,你申請這麼多權限,使用者在安裝App的時候,不是要崩潰了,尼瑪,這麼多看都看不過來啊,其實,根本不需要擔心,因為這些基本都是各自ROM中的第三方ROM權限,在使用者安裝的時候,他們通常會被解析成原生Launcher的權限,例如:添加、修改桌面快捷方式。并不會将所有的權限都寫出來。
建立快捷方式之——西域派
所謂西域派,是因為我想不出其他名字了。西域一派,使用其他方式來實作類似快捷方式的方法。
快捷方式的确是我們為應用導流的一個非常重要的入口,但是,由于碎片化實在太嚴重,是以,我們可以使用在Launcher App清單中為應用增加一個入口的方式來為App導流,簡單的說,就是增進一個App的入口Activity。
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.hujiang.hj_shortcut_lib.HJShortcutActivity"
android:theme="@style/Base.Theme.AppCompat.Dialog">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
非常簡單,相信大家都知道這種方式來給App增加一個Activity入口。但是,這種方式,我們如何能夠自由的控制這個入口是否顯示呢?
奇技PackageManager
PackageManager提供了一系列Package的管理方法,當然,也包含了我們非常關心的啟用、停用元件這一方法,這個方法在Root情況下,可以修改任一App的任意元件,在普通情況下,對自身App有絕對權限。使用方法也非常簡單:
public static void toggleFlowEntrance(Context context, Class launcherClass) {
PackageManager packageManager = context.getPackageManager();
ComponentName componentName = new ComponentName(context, launcherClass);
int res = packageManager.getComponentEnabledSetting(componentName);
if (res == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT ||
res == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
// 隐藏應用圖示
packageManager.setComponentEnabledSetting(
componentName,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
} else {
// 顯示應用圖示
packageManager.setComponentEnabledSetting(
componentName,
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
PackageManager.DONT_KILL_APP);
}
}
一統江湖
前面我們分析了各種快捷方式、Launcher入口的方式來對App進行導流,當然,這不是我們的目的,我們的目的是能夠掌握Android快捷方式的哭花寶典而不用那個啥。
是以,下面我封裝了一個shortcut的開源庫,進而可以盡可能的忽略ROM的差異,來使用快捷方式和Launcher入口。
項目位址:
https://github.com/xuyisheng/ShortcutHelper
目前該項目還在測試階段,還要很多問題和适配bug需要解決,歡迎大家提issue。
README如下:
ShortcutLib使用指南
本項目目前還在測試階段,請大家多提issue,共同完善。
項目意義
快速使用shortcut,避免各種ROM适配導緻的各種問題。
項目可用功能API
- 增加快捷方式
/**
* 添加快捷方式
*
* @param context context
* @param actionIntent 要啟動的Intent
* @param name name
* @param allowRepeat 是否允許重複
* @param iconBitmap 快捷方式圖示
*/
public static void addShortcut(Context context, Intent actionIntent, String name,
boolean allowRepeat, Bitmap iconBitmap)
- 判斷快捷方式是否存在
基礎方式
/**
* 判斷快捷方式是否存在
* <p/>
* 檢查快捷方式是否存在 <br/>
* <font color=red>注意:</font> 有些手機無法判斷是否已經建立過快捷方式<br/>
* 是以,在建立快捷方式時,請添加<br/>
* shortcutIntent.putExtra("duplicate", false);// 不允許重複建立<br/>
* 最好使用{@link #isShortCutExist(Context, String, Intent)}
* 進行判斷,因為可能有些應用生成的快捷方式名稱是一樣的的<br/>
*
* @param context context
* @param title 快捷方式名
* @return 是否存在
*/
public static boolean isShortCutExist(Context context, String title)
/**
* 判斷快捷方式是否存在
* <p/>
* 不一定所有的手機都有效,因為國内大部分手機的桌面不是系統原生的<br/>
* 更多請參考{@link #isShortCutExist(Context, String)}<br/>
* 桌面有兩種,系統桌面(ROM自帶)與第三方桌面,一般隻考慮系統自帶<br/>
* 第三方桌面如果沒有實作系統響應的方法是無法判斷的,比如GO桌面<br/>
*
* @param context context
* @param title 快捷方式名
* @param intent 快捷方式Intent
* @return 是否存在
*/
public static boolean isShortCutExist(Context context, String title, Intent intent)
更新快捷方式
/**
* 更新桌面快捷方式圖示,不一定所有圖示都有效(有可能需要系統權限)
*
* @param context context
* @param title 快捷方式名
* @param intent 快捷方式Intent
* @param bitmap 快捷方式Icon
*/
public static void updateShortcutIcon(Context context, String title, Intent intent, Bitmap bitmap)
/**
* 為任意PackageName的App添加快捷方式
*
* @param context context
* @param pkg 待添加快捷方式的應用包名
* @return 傳回true為正常執行完畢
*/
public static boolean addShortcutByPackageName(Context context, String pkg)
移除快捷方式
/**
* 移除快捷方式
*
* @param context context
* @param actionIntent 要啟動的Intent
* @param name name
*/
public static void removeShortcut(Context context, Intent actionIntent, String name)
顯示隐藏Launcher入口
/**
* 顯示\隐藏Launcher入口
*
* @param context context
* @param launcherClass launcherClass
*/
public static void toggleFlowEntrance(Context context, Class launcherClass)
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.xxx.xxxxx"
android:theme="@style/Base.Theme.AppCompat.Dialog">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
使用示例
public void addShortcutTest(View view) {
// 系統方式建立
// ShortcutUtils.addShortcut(this, getShortCutIntent(), mShortcutName);
// 建立前判斷是否存在
if (!ShortcutSuperUtils.isShortCutExist(this, mShortcutName, getShortCutIntent())) {
ShortcutUtils.addShortcut(this, getShortCutIntent(), mShortcutName, false,
BitmapFactory.decodeResource(getResources(), com.hujiang.hj_shortcut_lib.R.drawable.ocsplayer));
finish();
} else {
Toast.makeText(this, "Shortcut is exist!", Toast.LENGTH_SHORT).show();
}
// 為某個包建立快捷方式
// ShortcutSuperUtils.addShortcutByPackageName(this, this.getPackageName());
}
public void removeShortcutTest(View view) {
ShortcutUtils.removeShortcut(this, getShortCutIntent(), mShortcutName);
}
public void updateShortcutTest(View view) {
ShortcutSuperUtils.updateShortcutIcon(this, mShortcutName, getShortCutIntent(),
BitmapFactory.decodeResource(getResources(), com.hujiang.hj_shortcut_lib.R.mipmap.ic_launcher));
}
public void toggleFlowEntrance(View view) {
FlowEntranceUtil.toggleFlowEntrance(this, HJShortcutActivity.class);
}
private Intent getShortCutIntent() {
// 使用MAIN,可以避免部分手機(比如華為、HTC部分機型)删除應用時無法删除快捷方式的問題
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setClass(MainActivity.this, HJShortcutActivity.class);
return intent;
}