Merge "Improve shortcut demo" into nyc-dev
@@ -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))
|
||||
|
||||
66
samples/ShortcutDemo/common/res/layout/list_item.xml
Normal file
@@ -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>
|
||||
23
samples/ShortcutDemo/common/res/values/strings.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<?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.
|
||||
-->
|
||||
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<add-resource type="string" name="launch"/>
|
||||
<string name="launch">Launch</string>
|
||||
|
||||
<add-resource type="string" name="toggle"/>
|
||||
<string name="toggle">Toggle</string>
|
||||
</resources>
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
59
samples/ShortcutDemo/launcher/Android.mk
Normal file
@@ -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)
|
||||
32
samples/ShortcutDemo/launcher/AndroidManifest.xml
Normal file
@@ -0,0 +1,32 @@
|
||||
<?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.
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.example.android.pm.shortcutlauncherdemo">
|
||||
|
||||
<uses-sdk android:minSdkVersion="24" />
|
||||
|
||||
<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>
|
||||
</application>
|
||||
</manifest>
|
||||
30
samples/ShortcutDemo/launcher/res/layout/main.xml
Normal file
@@ -0,0 +1,30 @@
|
||||
<?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:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
<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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
19
samples/ShortcutDemo/launcher/res1/values/strings.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?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.
|
||||
-->
|
||||
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="app_title">[L1] Shortcuts Launcher Demo</string>
|
||||
</resources>
|
||||
19
samples/ShortcutDemo/launcher/res2/values/strings.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?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.
|
||||
-->
|
||||
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="app_title">[L2] Shortcuts Launcher Demo</string>
|
||||
</resources>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
61
samples/ShortcutDemo/publisher/Android.mk
Normal file
@@ -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)
|
||||
@@ -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>
|
||||
37
samples/ShortcutDemo/publisher/manifest2/AndroidManifest.xml
Normal file
@@ -0,0 +1,37 @@
|
||||
<?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.
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
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"
|
||||
android:resizeableActivity="true">
|
||||
<activity android:name="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.shortcutdemo2"
|
||||
android:name="IconProvider"/>
|
||||
</application>
|
||||
</manifest>
|
||||
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 131 KiB After Width: | Height: | Size: 131 KiB |
@@ -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>
|
||||
|
||||
|
||||
23
samples/ShortcutDemo/publisher/res/values/strings.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<?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.
|
||||
-->
|
||||
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<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>
|
||||
19
samples/ShortcutDemo/publisher/res1/values/strings.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?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.
|
||||
-->
|
||||
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="app_title">[P1] Shortcuts Demo</string>
|
||||
</resources>
|
||||
19
samples/ShortcutDemo/publisher/res2/values/strings.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?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.
|
||||
-->
|
||||
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="app_title">[P2] Shortcuts Demo</string>
|
||||
</resources>
|
||||
@@ -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;
|
||||
@@ -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 @@ import java.util.List;
|
||||
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 @@ public class Main extends Activity {
|
||||
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 @@ public class Main extends Activity {
|
||||
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();
|
||||
}
|
||||
}
|
||||