一、桌面组件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文件
<?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>
该文件主要是用来对widget的样式进行配置。
其中,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">
表示默认会被安装到手机内存中,具体关于手机应用的安装问题请看这一篇文章:
http://blog.csdn.net/shakespeare001/article/details/8171065
做好上述工作后,就可以进行测试了。
二、快捷方式shortcut
(可参考http://www.blogjava.net/sxyx2008/archive/2011/12/13/366228.html)
在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);
}
}
<?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。