Android桌面元件widget與快捷方式shortcut
一、桌面元件widget
1、新建一個Android工程,命名為WidgetDemo
2、建立widget佈局檔案
在res / layout下新建一個widget.xml佈局檔案
<?xml version="1.0"encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/sunset" > <TextView android:id="@+id/may1st" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" android:textSize="12px" android:textColor="#ff0000" /> </LinearLayout>
3、建立Widget內容提供者檔案
在res 下建立xml資料夾,然後在此資料夾下新建widget_provider.xml檔案
該檔案主要是用來對widget的樣式進行配置。<?xml version="1.0" encoding="utf-8"?> <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:minWidth="146dp" android:minHeight="72dp" android:updatePeriodMillis="1000" android:initialLayout="@layout/widget"> </appwidget-provider>
其中,android:minWidth和android:minHeight可以理解為手機螢幕上的格子數,而一個格子的寬度和高度都為72dp,所以這裡android:minWidth="146dp"和android:minHeight="146dp"表示該widget在手機螢幕上寬佔兩個格子,高度佔一個格子。
4、WidgetDemo.java程式碼如下
public class WidgetDemo extends AppWidgetProvider { private static final String CLICK_NAME_ACTION = "com.terry.action.widget.click"; public static boolean isChange = true; private static RemoteViews rv; /** * 呼叫機會: 1.達到指定的更新時候 2.使用者向桌面新增appwidget時辰 * 體系會發出一個android.appwidget.action.APPWIDGET_UPDATE廣播 * 按照AndroidManifest.xml註冊資訊,啟動widgetProvider,然後AppWidgetProvider接管 * 到廣播後,呼叫onUpdate辦法初始化 */ @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { System.out.println("onUpdate" + appWidgetIds.length); final int N = appWidgetIds.length; for (int i = 0; i < N; i++) { int appWidgetId = appWidgetIds[i]; AppWidget(context, appWidgetManager, appWidgetId); } } /** * 接管廣播,當點選TextView時,AppWidgetService會廣播一個事務 */ @Override public void onReceive(Context context, Intent intent) { super.onReceive(context, intent); System.out.println("onReceive:" + intent.getAction()); if (rv == null) { rv = new RemoteViews(context.getPackageName(), R.layout.main); } if (intent.getAction().equals(CLICK_NAME_ACTION)) { if (isChange) { rv.setTextViewText(R.id.TextView01, context.getResources() .getString(R.string.load)); } else { rv.setTextViewText(R.id.TextView01, context.getResources() .getString(R.string.change)); } Toast.makeText(context, Boolean.toString(isChange), Toast.LENGTH_LONG).show(); isChange = !isChange; // AppwidgetManager例項,更新appwidget AppWidgetManager appWidgetManger = AppWidgetManager .getInstance(context); int[] appIds = appWidgetManger.getAppWidgetIds(new ComponentName( context, widgetProvider.class)); appWidgetManger.AppWidget(appIds, rv); } } public static void AppWidget(Context context, AppWidgetManager appWidgeManger, int appWidgetId) { // 建立長途檢視例項 rv = new RemoteViews(context.getPackageName(), R.layout.main); // 建立點選意圖物件 Intent intentClick = new Intent(CLICK_NAME_ACTION); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intentClick, 0); // 繫結TextView點選事務 rv.setOnClickPendingIntent(R.id.TextView01, pendingIntent); // 通知AppWidgetService appWidgeManger.AppWidget(appWidgetId, rv); } /** * 刪除appwidget時呼叫 * 體系會發出一個android.appwidget.action.APPWIDGET_DELETED廣播 * 然後才呼叫onDeleted(Context context, int[] appWidgetIds) */ @Override public void onDeleted(Context context, int[] appWidgetIds) { super.onDeleted(context, appWidgetIds); System.out.println("onDeleted"); } /** * 第一個appwidget被建立時呼叫 * 體系會發出一個android.appwidget.action.APPWIDGET_ENABLED廣播 * 然後才呼叫onEnabled(Context context) */ @Override public void onEnabled(Context context) { super.onEnabled(context); System.out.println("onEnabled"); } /** * 最後一個appwidget被刪除 * 體系會發出一個android.appwidget.action.APPWIDGET_DISABLED廣播 * 然後才呼叫onDisabled(Context context) */ @Override public void onDisabled(Context context) { super.onDisabled(context); System.out.println("onDisabled"); } }
5、修改配置檔案AndroidManifest.xml
由於使用了reciever和“android.appwidget.action.APPWIDGET_UPDATE”,所以需要在AndroidManifest.xml中進行註冊。
<?xml version="1.0"encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.rui"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon"android:label="@string/app_name">
<receiver android:name=".WidgetDemo" android:label="@string/app_name">
<!-- 這個必須要加上,不然widget不會被建立 -->
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
</intent-filter>
<intent-filter>
<action android:name="com.terry.action.widget.click"/>
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/widget_provider"/>
</receiver>
6、設定應用安裝位置
由於手機只會列出安裝於手機記憶體中的APP,故還需要在AndroidManifest.xml檔案的android:installLocation="auto"
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.rui"
android:versionCode="1"
android:versionName="1.0"
android:installLocation="auto">
表示預設會被安裝到手機記憶體中,具體關於手機應用的安裝問題請看這一篇文章:
做好上述工作後,就可以進行測試了。
二、快捷方式shortcut
在Android中建立ShortCut大概有兩種方法。
第一種方法就是參照api demos中寫的那個,通過設定setResult(RESULT_OK, intent);來建立ShortCut,這種方式在稍後分析。
本文以Broadcast方式方式來介紹Android中ShortCut的建立。
在建立或刪除ShortCut的時候先需要在AndroidManifest.xml中增加兩個許可權
<!-- 建立桌面快捷方式的許可權 -->
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
<uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT"/>
另外記得在建立或刪除ShortCut的Intent中設定Action為
com.android.launcher.action.INSTALL_SHORTCUT(建立)
com.android.launcher.action.UNINSTALL_SHORTCUT(刪除)
這樣傳送出去的廣播才能被Android系統接受到
詳細程式碼:
package com.zhy.shortcut;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class ShortCutActivity extends Activity {
private static final String CREATE_SHORTCUT_ACTION = "com.android.launcher.action.INSTALL_SHORTCUT";
private static final String DROP_SHORTCUT_ACTION = "com.android.launcher.action.UNINSTALL_SHORTCUT";
private static final String PREFERENCE_KEY_SHORTCUT_EXISTS = "IsShortCutExists";
Button button;
// 獲取預設的SharedPreferences
SharedPreferences sharedPreferences ;
// 從SharedPreferences獲取是否存在快捷方式 若不存在返回false 程式第一次進來肯定返回false
boolean exists ;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
exists = sharedPreferences.getBoolean(PREFERENCE_KEY_SHORTCUT_EXISTS, false);
//建立桌面快捷方式
//若第一次啟動則建立,下次啟動則不建立
if (!exists) {
setUpShortCut();
}
setContentView(R.layout.main);
button = (Button) findViewById(R.id.dropShortCut);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
tearDownShortCut();
}
});
}
/**
* 建立桌面快捷方式
*/
private void setUpShortCut() {
Intent intent = new Intent(CREATE_SHORTCUT_ACTION);
// 設定快捷方式圖片
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,Intent.ShortcutIconResource.fromContext(this, R.drawable.logo));
// 設定快捷方式名稱
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "sina");
// 設定是否允許重複建立快捷方式 false表示不允許
intent.putExtra("duplicate", false);
// 設定快捷方式要開啟的intent
// 第一種方法建立快捷方式要開啟的目標intent
Intent targetIntent = new Intent();
// 設定應用程式解除安裝時同時也刪除桌面快捷方式
targetIntent.setAction(Intent.ACTION_MAIN);
targetIntent.addCategory("android.intent.category.LAUNCHER");
ComponentName componentName = new ComponentName(getPackageName(), this.getClass().getName());
targetIntent.setComponent(componentName);
// 第二種方法建立快捷方式要開啟的目標intent
/*
* Intent
* targetIntent=getPackageManager().getLaunchIntentForPackage(getPackageName
* ());
*/
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, targetIntent);
// 傳送廣播
sendBroadcast(intent);
Editor editor = sharedPreferences.edit();
editor.putBoolean(PREFERENCE_KEY_SHORTCUT_EXISTS, true);
editor.commit();
}
/**
* 刪除桌面快捷方式
*/
private void tearDownShortCut() {
Intent intent = new Intent(DROP_SHORTCUT_ACTION);
// 指定要刪除的shortcut名稱
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "sina");
String appClass = getPackageName() + "." + this.getLocalClassName();
ComponentName component = new ComponentName(getPackageName(), appClass);
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT,new Intent().setAction(Intent.ACTION_MAIN).setComponent(component));
sendBroadcast(intent);
}
}
AndroidManifest.xml檔案如下:<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.zhy.shortcut"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" />
<!-- 建立桌面快捷方式的許可權 -->
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
<uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT"/>
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:label="@string/app_name"
android:name=".ShortCutActivity" >
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
注意:該方式建立的ShortCut會在啟動應用的時候就建立ShortCut。