Improve shortcut demo
- Add launcher demo
- Now we build two of launchers and publishers, for better testing
Bug 27548047
Change-Id: Iede6abcf611261c83b7486f07709b56c6f5c53e0
diff --git a/samples/ShortcutDemo/Android.mk b/samples/ShortcutDemo/Android.mk
index 811649c..2ef28ee 100644
--- a/samples/ShortcutDemo/Android.mk
+++ b/samples/ShortcutDemo/Android.mk
@@ -1,16 +1,17 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
-LOCAL_MODULE_TAGS := samples tests
+LOCAL_PATH := $(call my-dir)
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := ShortcutDemo
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
-
-# Use the following include to make our test apk.
-include $(call all-makefiles-under,$(LOCAL_PATH))
+include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/samples/ShortcutDemo/common/res/layout/list_item.xml b/samples/ShortcutDemo/common/res/layout/list_item.xml
new file mode 100644
index 0000000..c99cc66
--- /dev/null
+++ b/samples/ShortcutDemo/common/res/layout/list_item.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+>
+ <ImageView
+ android:id="@+id/image"
+ android:layout_width="48dip"
+ android:layout_height="48dip"
+ android:layout_marginBottom="8dip"
+ />
+ <LinearLayout
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_gravity="center_vertical"
+ android:orientation="vertical"
+ android:paddingLeft="8dip"
+ >
+ <TextView
+ android:id="@+id/line1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textColor="#000000"
+ android:textSize="16sp"
+ />
+ <TextView
+ android:id="@+id/line2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textColor="#444444"
+ />
+ </LinearLayout>
+ <Button
+ android:id="@+id/launch"
+ android:text="@string/launch"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:gravity="center"
+ style="@android:style/Widget.Material.Button.Borderless"/>
+ <Button
+ android:id="@+id/toggle"
+ android:text="@string/toggle"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:gravity="center"
+ style="@android:style/Widget.Material.Button.Borderless"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/samples/ShortcutDemo/res/values/strings.xml b/samples/ShortcutDemo/common/res/values/strings.xml
similarity index 80%
copy from samples/ShortcutDemo/res/values/strings.xml
copy to samples/ShortcutDemo/common/res/values/strings.xml
index c466993..9ec96f1 100644
--- a/samples/ShortcutDemo/res/values/strings.xml
+++ b/samples/ShortcutDemo/common/res/values/strings.xml
@@ -15,6 +15,9 @@
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_title">Shortcuts Demo</string>
- <string name="publish">Publish shortcuts</string>
+ <add-resource type="string" name="launch"/>
+ <string name="launch">Launch</string>
+
+ <add-resource type="string" name="toggle"/>
+ <string name="toggle">Toggle</string>
</resources>
diff --git a/samples/ShortcutDemo/common/src/com/example/android/pm/shortcutdemo/AppLabelCache.java b/samples/ShortcutDemo/common/src/com/example/android/pm/shortcutdemo/AppLabelCache.java
new file mode 100644
index 0000000..ef05df5
--- /dev/null
+++ b/samples/ShortcutDemo/common/src/com/example/android/pm/shortcutdemo/AppLabelCache.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.android.pm.shortcutdemo;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.util.ArrayMap;
+
+public class AppLabelCache {
+ private final Context mContext;
+ private ArrayMap<String, String> mAppNames = new ArrayMap<>();
+
+ public AppLabelCache(Context context) {
+ mContext = context;
+ }
+
+ public String getAppLabel(String packageName) {
+ String name = mAppNames.get(packageName);
+ if (name != null) {
+ return name;
+ }
+ PackageManager pm = mContext.getPackageManager();
+ try {
+ final ApplicationInfo ai = pm.getApplicationInfo(packageName, 0);
+ name = pm.getApplicationLabel(ai).toString();
+ } catch (NameNotFoundException e) {
+ return packageName;
+ }
+ mAppNames.put(packageName, name);
+ return name;
+ }
+}
diff --git a/samples/ShortcutDemo/common/src/com/example/android/pm/shortcutdemo/ShortcutAdapter.java b/samples/ShortcutDemo/common/src/com/example/android/pm/shortcutdemo/ShortcutAdapter.java
new file mode 100644
index 0000000..4c28b1c
--- /dev/null
+++ b/samples/ShortcutDemo/common/src/com/example/android/pm/shortcutdemo/ShortcutAdapter.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.android.pm.shortcutdemo;
+
+import android.content.Context;
+import android.content.pm.LauncherApps;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ShortcutInfo;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.ParcelFileDescriptor;
+import android.os.Process;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import java.io.IOException;
+import java.util.List;
+
+public abstract class ShortcutAdapter extends BaseAdapter implements OnClickListener {
+ public static final String TAG = "ShortcutDemo";
+
+ private final Context mContext;
+ private final LayoutInflater mInflater;
+ private LauncherApps mLauncherApps;
+ private final AppLabelCache mAppLabelCache;
+ private List<ShortcutInfo> mShortcuts;
+
+ public ShortcutAdapter(Context context) {
+ mContext = context;
+ mAppLabelCache = new AppLabelCache(mContext);
+ mInflater = mContext.getSystemService(LayoutInflater.class);
+ mLauncherApps = mContext.getSystemService(LauncherApps.class);
+ }
+
+ protected abstract int getLayoutId();
+ protected abstract int getText1Id();
+ protected abstract int getText2Id();
+ protected abstract int getImageId();
+ protected abstract int getLaunchId();
+ protected abstract int getToggleId();
+
+ protected boolean showLaunch() {
+ return false;
+ }
+
+ protected boolean showToggle() {
+ return false;
+ }
+
+ protected String getToggleText(ShortcutInfo si) {
+ return "Toggle";
+ }
+
+ protected void onLaunchClicked(ShortcutInfo si) {
+ }
+
+ protected void onToggleClicked(ShortcutInfo si) {
+ }
+
+ public void setShortcuts(List<ShortcutInfo> shortcuts) {
+ mShortcuts = shortcuts;
+ notifyDataSetChanged();
+ }
+
+ public List<ShortcutInfo> getShortcuts() {
+ return mShortcuts;
+ }
+
+ @Override
+ public int getCount() {
+ return mShortcuts == null ? 0 : mShortcuts.size();
+ }
+
+ @Override
+ public Object getItem(int position) {
+ return mShortcuts.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public boolean hasStableIds() {
+ return false;
+ }
+
+ @Override
+ public boolean areAllItemsEnabled() {
+ return true;
+ }
+
+ @Override
+ public boolean isEnabled(int position) {
+ return true;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ final View view;
+ if (convertView != null) {
+ view = convertView;
+ } else {
+ view = mInflater.inflate(getLayoutId(), null);
+ }
+
+ bindView(view, position, mShortcuts.get(position));
+
+ return view;
+ }
+
+ public void bindView(View view, int position, ShortcutInfo si) {
+ if (showLaunch()) {
+ final View v = view.findViewById(getLaunchId());
+ v.setOnClickListener(this);
+ }
+ if (showToggle()) {
+ final Button v = (Button) view.findViewById(getToggleId());
+ v.setOnClickListener(this);
+ v.setText(getToggleText(si));
+ }
+
+ final TextView line1 = (TextView) view.findViewById(getText1Id());
+ final TextView line2 = (TextView) view.findViewById(getText2Id());
+
+ view.setTag(si);
+
+ line1.setText(si.getTitle());
+ line2.setText(
+ si.getId() + (si.isDynamic() ? " [dynamic]" : "")
+ + (si.isPinned() ? " [pinned]" : "") + "\n"
+ + mAppLabelCache.getAppLabel(si.getPackageName()));
+
+ // view.setBackgroundColor(si.isPinned() ? Color.rgb(255, 255, 192) : Color.WHITE);
+
+ // TODO Do it on worker thread
+ final ImageView image = (ImageView) view.findViewById(getImageId());
+ Bitmap icon = null;
+ if (si.hasIconResource()) {
+ try {
+ final Resources res = mContext.getPackageManager().getResourcesForApplication(
+ si.getPackageName());
+ icon = BitmapFactory.decodeResource(res,
+ mLauncherApps.getShortcutIconResId(si, Process.myUserHandle()));
+
+ } catch (NameNotFoundException e) {
+ Log.w(TAG, "Unable to load icon from " + si.getPackageName(), e);
+ }
+ } else if (si.hasIconFile()) {
+ icon = pfdToBitmap(mLauncherApps.getShortcutIconFd(si, Process.myUserHandle()));
+ }
+ image.setImageBitmap(icon);
+ }
+
+ private Bitmap pfdToBitmap(ParcelFileDescriptor pfd) {
+ if (pfd == null) {
+ return null;
+ }
+ try {
+ final Bitmap bmp = BitmapFactory.decodeFileDescriptor(pfd.getFileDescriptor());
+ if (bmp == null) {
+ Log.w(TAG, "Failed to decode icon");
+ }
+ return bmp;
+ } finally {
+ try {
+ pfd.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+
+ @Override
+ public void onClick(View v) {
+ final ShortcutInfo si = (ShortcutInfo)(((View) v.getParent()).getTag());
+ if (v.getId() == getLaunchId()) {
+ onLaunchClicked(si);
+ } else if (v.getId() == getToggleId()) {
+ onToggleClicked(si);
+ }
+ }
+}
diff --git a/samples/ShortcutDemo/launcher/Android.mk b/samples/ShortcutDemo/launcher/Android.mk
new file mode 100644
index 0000000..2d69320
--- /dev/null
+++ b/samples/ShortcutDemo/launcher/Android.mk
@@ -0,0 +1,59 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# We build two apps from the same source
+
+LOCAL_PATH:= $(call my-dir)
+
+# === App 1 ===
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := ShortcutLauncherDemo
+
+LOCAL_MODULE_TAGS := samples tests
+
+LOCAL_AAPT_FLAGS += --rename-manifest-package com.example.android.pm.shortcutlauncherdemo
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SRC_FILES += $(call all-java-files-under, ../common/src)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_RESOURCE_DIR += $(LOCAL_PATH)/../common/res
+LOCAL_RESOURCE_DIR += $(LOCAL_PATH)/res1
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
+
+# === App 2 ===
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := ShortcutLauncherDemo2
+
+LOCAL_MODULE_TAGS := samples tests
+
+LOCAL_AAPT_FLAGS += --rename-manifest-package com.example.android.pm.shortcutlauncherdemo2
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SRC_FILES += $(call all-java-files-under, ../common/src)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_RESOURCE_DIR += $(LOCAL_PATH)/../common/res
+LOCAL_RESOURCE_DIR += $(LOCAL_PATH)/res2
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/samples/ShortcutDemo/AndroidManifest.xml b/samples/ShortcutDemo/launcher/AndroidManifest.xml
similarity index 72%
copy from samples/ShortcutDemo/AndroidManifest.xml
copy to samples/ShortcutDemo/launcher/AndroidManifest.xml
index bce132f..c3257bb 100644
--- a/samples/ShortcutDemo/AndroidManifest.xml
+++ b/samples/ShortcutDemo/launcher/AndroidManifest.xml
@@ -15,22 +15,18 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.example.android.pm.shortcuts">
+ package="com.example.android.pm.shortcutlauncherdemo">
<uses-sdk android:minSdkVersion="24" />
- <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-
- <application android:label="@string/app_title">
- <activity android:name="Main">
+ <application android:label="@string/app_title"
+ android:resizeableActivity="true">
+ <activity android:name="com.example.android.pm.shortcutlauncherdemo.Main">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
- <provider android:authorities="com.example.android.pm.shortcuts"
- android:name="IconProvider"/>
</application>
</manifest>
diff --git a/samples/ShortcutDemo/res/layout/main.xml b/samples/ShortcutDemo/launcher/res/layout/main.xml
similarity index 77%
copy from samples/ShortcutDemo/res/layout/main.xml
copy to samples/ShortcutDemo/launcher/res/layout/main.xml
index c59aedc..bb24877 100644
--- a/samples/ShortcutDemo/res/layout/main.xml
+++ b/samples/ShortcutDemo/launcher/res/layout/main.xml
@@ -17,12 +17,14 @@
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
- <Button
- android:id="@+id/button1"
- android:text="@string/publish"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:onClick="onPublishPressed"/>
+ <ListView
+ android:id="@android:id/list"
+ android:layout_width="match_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1"
+ android:choiceMode="multipleChoice"
+ android:enabled="true"
+ />
</LinearLayout>
diff --git a/samples/ShortcutDemo/res/values/strings.xml b/samples/ShortcutDemo/launcher/res/values/strings.xml
similarity index 87%
copy from samples/ShortcutDemo/res/values/strings.xml
copy to samples/ShortcutDemo/launcher/res/values/strings.xml
index c466993..66c78aa 100644
--- a/samples/ShortcutDemo/res/values/strings.xml
+++ b/samples/ShortcutDemo/launcher/res/values/strings.xml
@@ -15,6 +15,4 @@
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_title">Shortcuts Demo</string>
- <string name="publish">Publish shortcuts</string>
</resources>
diff --git a/samples/ShortcutDemo/res/values/strings.xml b/samples/ShortcutDemo/launcher/res1/values/strings.xml
similarity index 87%
copy from samples/ShortcutDemo/res/values/strings.xml
copy to samples/ShortcutDemo/launcher/res1/values/strings.xml
index c466993..ba09d82 100644
--- a/samples/ShortcutDemo/res/values/strings.xml
+++ b/samples/ShortcutDemo/launcher/res1/values/strings.xml
@@ -15,6 +15,5 @@
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_title">Shortcuts Demo</string>
- <string name="publish">Publish shortcuts</string>
+ <string name="app_title">[L1] Shortcuts Launcher Demo</string>
</resources>
diff --git a/samples/ShortcutDemo/res/values/strings.xml b/samples/ShortcutDemo/launcher/res2/values/strings.xml
similarity index 87%
copy from samples/ShortcutDemo/res/values/strings.xml
copy to samples/ShortcutDemo/launcher/res2/values/strings.xml
index c466993..f27cccc 100644
--- a/samples/ShortcutDemo/res/values/strings.xml
+++ b/samples/ShortcutDemo/launcher/res2/values/strings.xml
@@ -15,6 +15,5 @@
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_title">Shortcuts Demo</string>
- <string name="publish">Publish shortcuts</string>
+ <string name="app_title">[L2] Shortcuts Launcher Demo</string>
</resources>
diff --git a/samples/ShortcutDemo/launcher/src/com/example/android/pm/shortcutlauncherdemo/Main.java b/samples/ShortcutDemo/launcher/src/com/example/android/pm/shortcutlauncherdemo/Main.java
new file mode 100644
index 0000000..20cd4ec
--- /dev/null
+++ b/samples/ShortcutDemo/launcher/src/com/example/android/pm/shortcutlauncherdemo/Main.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.android.pm.shortcutlauncherdemo;
+
+import android.app.ListActivity;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.LauncherApps;
+import android.content.pm.LauncherApps.ShortcutQuery;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ShortcutInfo;
+import android.os.Bundle;
+import android.os.Process;
+import android.os.UserHandle;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.view.View;
+import android.widget.ListView;
+
+import com.example.android.pm.shortcutdemo.ShortcutAdapter;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+public class Main extends ListActivity {
+ public static final String TAG = "ShortcutLauncherDemo";
+
+ private LauncherApps mLauncherApps;
+
+ private MyAdapter mAdapter;
+
+ private ArrayMap<String, String> mAppNames = new ArrayMap<>();
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.main);
+
+ mLauncherApps = getSystemService(LauncherApps.class);
+ mLauncherApps.registerCallback(mLauncherCallback);
+
+ mAdapter = new MyAdapter(this);
+
+ setListAdapter(mAdapter);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ refreshList();
+ }
+
+ @Override
+ protected void onDestroy() {
+ mLauncherApps.unregisterCallback(mLauncherCallback);
+
+ super.onDestroy();
+ }
+
+ private void togglePin(ShortcutInfo selected) {
+ final String packageName = selected.getPackageName();
+
+ final List<String> pinned = new ArrayList<>();
+ for (ShortcutInfo si : mAdapter.getShortcuts()) {
+ if (si.isPinned() && si.getPackageName().equals(packageName)) {
+ pinned.add(si.getId());
+ }
+ }
+ if (selected.isPinned()) {
+ pinned.remove(selected.getId());
+ } else {
+ pinned.add(selected.getId());
+ }
+ mLauncherApps.pinShortcuts(packageName, pinned, Process.myUserHandle());
+ }
+
+ private void launch(ShortcutInfo si) {
+ mLauncherApps.startShortcut(si.getPackageName(), si.getId(), null, null,
+ Process.myUserHandle());
+ }
+
+ private String getAppLabel(String packageName) {
+ String name = mAppNames.get(packageName);
+ if (name != null) {
+ return name;
+ }
+ PackageManager pm = getPackageManager();
+ try {
+ final ApplicationInfo ai = pm.getApplicationInfo(packageName, 0);
+ return pm.getApplicationLabel(ai).toString();
+ } catch (NameNotFoundException e) {
+ return packageName;
+ }
+ }
+
+ private void refreshList() {
+ final ShortcutQuery q = new ShortcutQuery();
+ q.setQueryFlags(ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_PINNED);
+
+ final List<ShortcutInfo> list = mLauncherApps.getShortcuts(q, Process.myUserHandle());
+ Collections.sort(list, mShortcutComparator);
+ Log.i(TAG, "All shortcuts:");
+ for (ShortcutInfo si : list) {
+ Log.i(TAG, si.toString());
+ }
+
+ mAdapter.setShortcuts(list);
+ }
+
+ private final Comparator<ShortcutInfo> mShortcutComparator =
+ (ShortcutInfo s1, ShortcutInfo s2) -> {
+ int ret = 0;
+ ret = getAppLabel(s1.getPackageName()).compareTo(getAppLabel(s2.getPackageName()));
+ if (ret != 0) return ret;
+
+ ret = s1.getTitle().compareTo(s2.getTitle());
+ if (ret != 0) return ret;
+
+ ret = s1.getId().compareTo(s2.getId());
+ if (ret != 0) return ret;
+
+ return 0;
+ };
+
+ private final LauncherApps.Callback mLauncherCallback = new LauncherApps.Callback() {
+ @Override
+ public void onPackageRemoved(String packageName, UserHandle user) {
+ }
+
+ @Override
+ public void onPackageAdded(String packageName, UserHandle user) {
+ }
+
+ @Override
+ public void onPackageChanged(String packageName, UserHandle user) {
+ }
+
+ @Override
+ public void onPackagesAvailable(String[] packageNames, UserHandle user, boolean replacing) {
+ }
+
+ @Override
+ public void onPackagesUnavailable(String[] packageNames, UserHandle user,
+ boolean replacing) {
+ }
+
+ @Override
+ public void onShortcutsChanged(String packageName,
+ List<ShortcutInfo> shortcuts, UserHandle user) {
+ Log.w(TAG, "onShortcutsChanged: user=" + user + " package=" + packageName);
+ refreshList();
+ }
+ };
+
+ class MyAdapter extends ShortcutAdapter {
+ public MyAdapter(Context context) {
+ super(context);
+ }
+
+ @Override
+ protected int getLayoutId() {
+ return R.layout.list_item;
+ }
+
+ @Override
+ protected int getText1Id() {
+ return R.id.line1;
+ }
+
+ @Override
+ protected int getText2Id() {
+ return R.id.line2;
+ }
+
+ @Override
+ protected int getImageId() {
+ return R.id.image;
+ }
+
+ @Override
+ protected int getLaunchId() {
+ return R.id.launch;
+ }
+
+ @Override
+ protected int getToggleId() {
+ return R.id.toggle;
+ }
+
+ @Override
+ protected boolean showLaunch() {
+ return true;
+ }
+
+ @Override
+ protected boolean showToggle() {
+ return true;
+ }
+
+ @Override
+ protected String getToggleText(ShortcutInfo si) {
+ return si.isPinned() ? "Unpin" : "Pin";
+ }
+
+ @Override
+ protected void onLaunchClicked(ShortcutInfo si) {
+ launch(si);
+ }
+
+ @Override
+ protected void onToggleClicked(ShortcutInfo si) {
+ togglePin(si);
+ }
+ }
+}
diff --git a/samples/ShortcutDemo/publisher/Android.mk b/samples/ShortcutDemo/publisher/Android.mk
new file mode 100644
index 0000000..bf0ac47
--- /dev/null
+++ b/samples/ShortcutDemo/publisher/Android.mk
@@ -0,0 +1,61 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# We build two apps from the same source
+
+LOCAL_PATH:= $(call my-dir)
+
+# === App 1 ===
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := ShortcutDemo
+
+LOCAL_MODULE_TAGS := samples tests
+
+LOCAL_MANIFEST_FILE := manifest1/AndroidManifest.xml
+LOCAL_AAPT_FLAGS += --rename-manifest-package com.example.android.pm.shortcutdemo
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+#LOCAL_SRC_FILES += $(call all-java-files-under, ../common/src)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_RESOURCE_DIR += $(LOCAL_PATH)/../common/res
+LOCAL_RESOURCE_DIR += $(LOCAL_PATH)/res1
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
+
+# === App 2 ===
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := ShortcutDemo2
+
+LOCAL_MODULE_TAGS := samples tests
+
+LOCAL_MANIFEST_FILE := manifest2/AndroidManifest.xml
+LOCAL_AAPT_FLAGS += --rename-manifest-package com.example.android.pm.shortcutdemo2
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+#LOCAL_SRC_FILES += $(call all-java-files-under, ../common/src)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_RESOURCE_DIR += $(LOCAL_PATH)/../common/res
+LOCAL_RESOURCE_DIR += $(LOCAL_PATH)/res2
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/samples/ShortcutDemo/AndroidManifest.xml b/samples/ShortcutDemo/publisher/manifest1/AndroidManifest.xml
similarity index 89%
rename from samples/ShortcutDemo/AndroidManifest.xml
rename to samples/ShortcutDemo/publisher/manifest1/AndroidManifest.xml
index bce132f..1a3ed36 100644
--- a/samples/ShortcutDemo/AndroidManifest.xml
+++ b/samples/ShortcutDemo/publisher/manifest1/AndroidManifest.xml
@@ -15,14 +15,15 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.example.android.pm.shortcuts">
+ package="com.example.android.pm.shortcutdemo">
<uses-sdk android:minSdkVersion="24" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- <application android:label="@string/app_title">
+ <application android:label="@string/app_title"
+ android:resizeableActivity="true">
<activity android:name="Main">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -30,7 +31,7 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
- <provider android:authorities="com.example.android.pm.shortcuts"
+ <provider android:authorities="com.example.android.pm.shortcutdemo"
android:name="IconProvider"/>
</application>
</manifest>
diff --git a/samples/ShortcutDemo/AndroidManifest.xml b/samples/ShortcutDemo/publisher/manifest2/AndroidManifest.xml
similarity index 89%
copy from samples/ShortcutDemo/AndroidManifest.xml
copy to samples/ShortcutDemo/publisher/manifest2/AndroidManifest.xml
index bce132f..887f379 100644
--- a/samples/ShortcutDemo/AndroidManifest.xml
+++ b/samples/ShortcutDemo/publisher/manifest2/AndroidManifest.xml
@@ -15,14 +15,15 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.example.android.pm.shortcuts">
+ package="com.example.android.pm.shortcutdemo">
<uses-sdk android:minSdkVersion="24" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- <application android:label="@string/app_title">
+ <application android:label="@string/app_title"
+ android:resizeableActivity="true">
<activity android:name="Main">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -30,7 +31,7 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
- <provider android:authorities="com.example.android.pm.shortcuts"
+ <provider android:authorities="com.example.android.pm.shortcutdemo2"
android:name="IconProvider"/>
</application>
</manifest>
diff --git a/samples/ShortcutDemo/res/drawable-nodpi/icon1.png b/samples/ShortcutDemo/publisher/res/drawable-nodpi/icon1.png
similarity index 100%
rename from samples/ShortcutDemo/res/drawable-nodpi/icon1.png
rename to samples/ShortcutDemo/publisher/res/drawable-nodpi/icon1.png
Binary files differ
diff --git a/samples/ShortcutDemo/res/drawable-nodpi/icon2.png b/samples/ShortcutDemo/publisher/res/drawable-nodpi/icon2.png
similarity index 100%
rename from samples/ShortcutDemo/res/drawable-nodpi/icon2.png
rename to samples/ShortcutDemo/publisher/res/drawable-nodpi/icon2.png
Binary files differ
diff --git a/samples/ShortcutDemo/res/drawable-nodpi/icon_large_1.png b/samples/ShortcutDemo/publisher/res/drawable-nodpi/icon_large_1.png
similarity index 100%
rename from samples/ShortcutDemo/res/drawable-nodpi/icon_large_1.png
rename to samples/ShortcutDemo/publisher/res/drawable-nodpi/icon_large_1.png
Binary files differ
diff --git a/samples/ShortcutDemo/res/drawable-nodpi/icon_large_2.png b/samples/ShortcutDemo/publisher/res/drawable-nodpi/icon_large_2.png
similarity index 100%
rename from samples/ShortcutDemo/res/drawable-nodpi/icon_large_2.png
rename to samples/ShortcutDemo/publisher/res/drawable-nodpi/icon_large_2.png
Binary files differ
diff --git a/samples/ShortcutDemo/res/drawable-nodpi/icon_large_3.png b/samples/ShortcutDemo/publisher/res/drawable-nodpi/icon_large_3.png
similarity index 100%
rename from samples/ShortcutDemo/res/drawable-nodpi/icon_large_3.png
rename to samples/ShortcutDemo/publisher/res/drawable-nodpi/icon_large_3.png
Binary files differ
diff --git a/samples/ShortcutDemo/res/layout/main.xml b/samples/ShortcutDemo/publisher/res/layout/main.xml
similarity index 80%
rename from samples/ShortcutDemo/res/layout/main.xml
rename to samples/ShortcutDemo/publisher/res/layout/main.xml
index c59aedc..f2dc492 100644
--- a/samples/ShortcutDemo/res/layout/main.xml
+++ b/samples/ShortcutDemo/publisher/res/layout/main.xml
@@ -18,11 +18,17 @@
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button
- android:id="@+id/button1"
+ android:id="@+id/publish"
android:text="@string/publish"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="onPublishPressed"/>
+ <Button
+ android:id="@+id/delete_all"
+ android:text="@string/delete_all"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:onClick="onDeleteAllPressed"/>
</LinearLayout>
diff --git a/samples/ShortcutDemo/res/values/strings.xml b/samples/ShortcutDemo/publisher/res/values/strings.xml
similarity index 82%
copy from samples/ShortcutDemo/res/values/strings.xml
copy to samples/ShortcutDemo/publisher/res/values/strings.xml
index c466993..548c9d4 100644
--- a/samples/ShortcutDemo/res/values/strings.xml
+++ b/samples/ShortcutDemo/publisher/res/values/strings.xml
@@ -15,6 +15,9 @@
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_title">Shortcuts Demo</string>
+ <add-resource type="string" name="publish"/>
<string name="publish">Publish shortcuts</string>
+
+ <add-resource type="string" name="delete_all"/>
+ <string name="delete_all">Delete all dynamic shortcuts</string>
</resources>
diff --git a/samples/ShortcutDemo/res/values/strings.xml b/samples/ShortcutDemo/publisher/res1/values/strings.xml
similarity index 87%
copy from samples/ShortcutDemo/res/values/strings.xml
copy to samples/ShortcutDemo/publisher/res1/values/strings.xml
index c466993..aed1197 100644
--- a/samples/ShortcutDemo/res/values/strings.xml
+++ b/samples/ShortcutDemo/publisher/res1/values/strings.xml
@@ -15,6 +15,5 @@
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_title">Shortcuts Demo</string>
- <string name="publish">Publish shortcuts</string>
+ <string name="app_title">[P1] Shortcuts Demo</string>
</resources>
diff --git a/samples/ShortcutDemo/res/values/strings.xml b/samples/ShortcutDemo/publisher/res2/values/strings.xml
similarity index 87%
rename from samples/ShortcutDemo/res/values/strings.xml
rename to samples/ShortcutDemo/publisher/res2/values/strings.xml
index c466993..04fdf03 100644
--- a/samples/ShortcutDemo/res/values/strings.xml
+++ b/samples/ShortcutDemo/publisher/res2/values/strings.xml
@@ -15,6 +15,5 @@
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_title">Shortcuts Demo</string>
- <string name="publish">Publish shortcuts</string>
+ <string name="app_title">[P2] Shortcuts Demo</string>
</resources>
diff --git a/samples/ShortcutDemo/src/com/example/android/pm/shortcuts/IconProvider.java b/samples/ShortcutDemo/publisher/src/com/example/android/pm/shortcutdemo/IconProvider.java
similarity index 98%
rename from samples/ShortcutDemo/src/com/example/android/pm/shortcuts/IconProvider.java
rename to samples/ShortcutDemo/publisher/src/com/example/android/pm/shortcutdemo/IconProvider.java
index 83e84bd..e2c5254 100644
--- a/samples/ShortcutDemo/src/com/example/android/pm/shortcuts/IconProvider.java
+++ b/samples/ShortcutDemo/publisher/src/com/example/android/pm/shortcutdemo/IconProvider.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.example.android.pm.shortcuts;
+package com.example.android.pm.shortcutdemo;
import android.content.ContentProvider;
import android.content.ContentProvider.PipeDataWriter;
diff --git a/samples/ShortcutDemo/src/com/example/android/pm/shortcuts/Main.java b/samples/ShortcutDemo/publisher/src/com/example/android/pm/shortcutdemo/Main.java
similarity index 61%
rename from samples/ShortcutDemo/src/com/example/android/pm/shortcuts/Main.java
rename to samples/ShortcutDemo/publisher/src/com/example/android/pm/shortcutdemo/Main.java
index 68edb82..7a687e8 100644
--- a/samples/ShortcutDemo/src/com/example/android/pm/shortcuts/Main.java
+++ b/samples/ShortcutDemo/publisher/src/com/example/android/pm/shortcutdemo/Main.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.example.android.pm.shortcuts;
+package com.example.android.pm.shortcutdemo;
import android.app.Activity;
import android.app.WallpaperManager;
@@ -42,10 +42,7 @@
public class Main extends Activity {
public static final String TAG = "ShortcutDemo";
- private static final boolean USE_LAUNCHER_APIS = true;
-
private ShortcutManager mShortcutManager;
- private LauncherApps mLauncherApps;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -54,23 +51,10 @@
setContentView(R.layout.main);
mShortcutManager = getSystemService(ShortcutManager.class);
- mLauncherApps = getSystemService(LauncherApps.class);
-
- // TODO This will break once LauncherApps implements permission checks.
- if (USE_LAUNCHER_APIS) {
- mLauncherApps.registerCallback(mLauncherCallback);
- }
-
- WallpaperManager wpm = this.getSystemService(WallpaperManager.class);
- wpm.getWallpaperFile(WallpaperManager.FLAG_SET_LOCK);
}
@Override
protected void onDestroy() {
- if (USE_LAUNCHER_APIS) {
- mLauncherApps.unregisterCallback(mLauncherCallback);
- }
-
super.onDestroy();
}
@@ -139,62 +123,9 @@
if (!mShortcutManager.setDynamicShortcuts(Arrays.asList(si1, si2, si3))) {
showThrottledToast();
}
- mLauncherApps.startShortcut(this.getPackageName(), "shortcut1", null, null, Process.myUserHandle());
}
- private final LauncherApps.Callback mLauncherCallback = new LauncherApps.Callback() {
- @Override
- public void onPackageRemoved(String packageName, UserHandle user) {
- }
-
- @Override
- public void onPackageAdded(String packageName, UserHandle user) {
- }
-
- @Override
- public void onPackageChanged(String packageName, UserHandle user) {
- }
-
- @Override
- public void onPackagesAvailable(String[] packageNames, UserHandle user, boolean replacing) {
- }
-
- @Override
- public void onPackagesUnavailable(String[] packageNames, UserHandle user,
- boolean replacing) {
- }
-
- @Override
- public void onShortcutsChanged(String packageName,
- List<ShortcutInfo> shortcuts, UserHandle user) {
- Log.w(TAG, "onShortcutsChanged: user=" + user + " package=" + packageName);
- Log.d(TAG, "Updated shortcuts:");
- for (ShortcutInfo si : shortcuts) {
- Log.d(TAG, " " + si.toString());
- writeIconToFile(si);
- }
- }
- };
-
- private void writeIconToFile(ShortcutInfo si) {
- if (!si.hasIconFile()){
- return;
- }
- String filename = Environment.getExternalStorageDirectory() + "/" + si.getId() + ".png";
- try (
- ParcelFileDescriptor pfd = mLauncherApps.getShortcutIconFd(si,
- Process.myUserHandle());
- FileInputStream in = new FileInputStream(pfd.getFileDescriptor());
- FileOutputStream out = new FileOutputStream(filename)) {
-
- byte[] buf = new byte[32 * 1024];
- int len;
- while ((len = in.read(buf)) >= 0) {
- out.write(buf, 0, len);
- }
- Log.d(TAG, "wrote icon to " + filename);
- } catch (IOException e) {
- e.printStackTrace();
- }
+ public void onDeleteAllPressed(View view) {
+ mShortcutManager.deleteAllDynamicShortcuts();
}
}