Merge "Improve shortcut demo" into nyc-dev

This commit is contained in:
Makoto Onuki
2016-03-10 19:36:07 +00:00
committed by Android (Google) Code Review
26 changed files with 921 additions and 93 deletions

View File

@@ -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))

View 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>

View 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>

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}

View 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)

View 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>

View 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>

View File

@@ -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>

View 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>

View 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>

View File

@@ -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);
}
}
}

View 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)

View File

@@ -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>

View 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>

View File

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 57 KiB

View File

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 44 KiB

View File

Before

Width:  |  Height:  |  Size: 131 KiB

After

Width:  |  Height:  |  Size: 131 KiB

View File

@@ -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>

View 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>

View 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>

View 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>

View File

@@ -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;

View File

@@ -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();
}
}