实现动态壁纸是不需要使用Activity的, 创建MyWallPaper类,让其继承WallpaperService:
实现 onCreateEngine()方法,返回自己实现的Engine类,在Engine类中实现核心代码。
首先在AndroidManifest.xml中注册service->MyWallPaper
<service
android:label="@string/app_name"
android:permission="android.permission.BIND_WALLPAPER"
android:name=".MyWallPaper">
<intent-filter>
<!-- 隐式Intent不指明目标组件的class,只定义希望的Action及Data等相关信息,由系统决定使用哪个目标组件。 -->
<action android:name="android.service.wallpaper.WallpaperService" />
</intent-filter>
<meta-data android:name="android.service.wallpaper"
android:resource="@xml/bubblelivewallpaper" />
</service>
添加权限
<uses-permission android:name = "android.permission.SET_WALLPAPER"/>
下面解释一下<intent-filter>,<mata-data>
1、Intent和Intent Filter的介绍及作用
Android包含四大组件Activity、Service、Broadcast Receiver、Content Provider。其中的Activity、Service、Broadcast Receiver之间如何进行通信,如当前处在Activity A,如何切换到ActivityB,如何启动一个Service,如何注册一个Broadcast,如何发送一条短信,如何打开本机的地图或是浏览器呢,这些都要用到Intent。
Intent是抽象的数据结构,包含了一系列描述某个操作的数据,使得程序在运行时可以在程序中不同组件间通信或启动不同的应用程序。可以通过startActivity(Intent)
启动一个Activity, sendBroadcast(Intent)发送广播发送给感兴趣的BroadcastReceiver组件, startService(Intent)启动service,bindService(Intent, ServiceConnection, int)绑定服务。
Intent Filter顾名思义就是Intent的过滤器,组件通过定义Intent Filter可以决定哪些隐式Intent可以和该组件进行通讯。关于隐式Intent的定义后面会进行介绍,Intent Filter对显式的Intent不起作用。
2、Intent结构
Intent结构如下
private String mAction; private Uri mData; private String mType; private String mPackage; private ComponentName mComponent; private int mFlags; private HashSet<String> mCategories; private Bundle mExtras; private Rect mSourceBounds;
Intent的主要成员是mAction和mData
Action就是个String类型的字符串,在隐式Intent中用来和filter进行匹配的关键指标,如ACTION_VIEW,ACTION_EDIT等,Intent内置了很多Action常量,我们也可以自定义私有Action方便自己进行匹配。
Data为Uri类型的数据,若mType为空通过对mData的解析可以得到数据的类型。
Component表示组件信息,包含context和目标组件的class信息,设置了即为显示Intent。
Category作为决定哪个组件处理Intent的附属信息,一个Intent可以添加或删除多个Category存储在mCategories。
Flag用于标记如何启动一个活动,是NEW_TASK还是其他等等,以及启动后怎么对待这个活动。
Extras为附加信息,会传递给目标组件,比如发送邮件,Extras可以存储邮件收件人地址、内容、主题、附件等信息。
因为Intent Filter和Intent的匹配只有三个字段起作用,所以Intent Filter只包含Actions、Datas、Categorys三个属性(实际源码中会将Data划分为多个部分),属性的意义和Intent相同。不同的是Intent Filter可以包含多个Action、多个Data、多个Category,而Intent除Category可以有多个外,只能有一个Action、一个Data。
3、两种类型的Intent
对于一个定义好的Intent,Android如何判断和哪个目标组件通讯呢。Intent分为隐式(implicit)Intent和显式(explicit)Intent。
显式Intent通常用于在程序内部组件间通信,已经明确的定义目标组件的信息,所以不需要系统决策哪个目标组件处理Intent,如下
Intent intent = new Intent(DemoList.this, GoogleMapDemo.class); startActivity(intent);
其中DemoList和GoogleMapDemo都是用户自定义的组件,
隐式Intent不指明目标组件的class,只定义希望的Action及Data等相关信息,由系统决定使用哪个目标组件。如发送短信
Uri uri = Uri.parse("smsto:15800000000");
Intent i = new Intent(Intent.ACTION_SENDTO, uri);
i.putExtra("sms_body", "The SMS text");
startActivity(i);
这也是Android系统设计的一个亮点之一,通过隐式的Intent可以方便的调用其他程序的组件,比如调用地图、短息、打电话、拍照组件为自己的程序所用。这里就涉及下一个问题,系统如何决定目标组件呢?
4、Intent和<intent-filter>的匹配规则
Android系统通过对Intent和目标组件在AndroidManifest文件中定义的<intent-filter>(也可以在程序中定义Intent Filter)进行匹配决定和哪个目标组件通讯。如果某组件未定义<intent-filter>则只能通过显式的Intent进行通信。Intent的三个属性用于对目标组件选取的决策,分别是Action、Data(Uri和Data Type)、Category。匹配规则如下
a. Intent定义的Action必须包含在<intent-filter>的Action列表中,若隐式Intent未定义Action系统会报错。由此可知一个<intent-filter>至少包含一个Action。
b. 未定义Uri和Type的Intent仅可以通过不包含包含Uri和Type的filter;包含了Uri,不包含Type的Intent仅可以通过包含匹配Uri不包含Type的filter;包含了Type不包含Uri的Intent仅可以通过包含了相同Type不包含Uri的filter;同时包含了Uri和Type的Intent仅可以通过相同Type匹配Uri(或不包含Uri但Intent Uri为content:或file:)的filter。
c. Intent若定义了Category(可多个),则所有Category必需包含在<intent-filter>的Category列表中。若Intent未定义Category,则<intent-filter>是否定义Category不影响。
PS:<intent-filter>必须包含<category android:name="android.intent.category.DEFAULT" />才能通过startActivity启动,所以Activity的<intent-filter>至少包含一个category,Service和BroadcastReceiver不必。
目标组件必须包含同时满足以上规则的<intent-filter>才能进行匹配。若有多个目标组件同时可以匹配,则系统会提示用户进行选择,若没有目标组件可以匹配系统会进行提示。
如某组件filter如下
<intent-filter android:label="@string/resolve_edit"> <action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.EDIT" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="vnd.android.cursor.item/vnd.google.note" /> </intent-filter>
则{action=android.intent.action.INSERT}不可以通过
{action=android.intent.action.VIEW category=android.intent.category.ALTERNATIVE}不可以通过
{action=android.intent.action.VIEW data=content://com.google.provider.NotePad/notes/{ID}}可以通过
{action=android.intent.action.VIEW data=smsto:15800000000}不可以通过
Android读取 meta_data元素的数据
在AndroidManifest.xml中,<meta-data>元素可以作为子元素,被包含在<activity>、<application> 、<service>和<receiver>元素中,但
不同的父元素,在应用时读取的方法也不同。
1 :在Activity的应用。
xml代码段:
<activity...>
<meta-data android:name="myMsg" android:value="hello my activity"></meta-data>
</activity>
java代码段:
<activity...>
<meta-data android:name="myMsg" android:value="hello my activity"></meta-data>
</activity>
ActivityInfo info=this.getPackageManager()
.getActivityInfo(getComponentName(),
PackageManager.GET_META_DATA);
String msg=info.metaData.getString("myMsg");
System.out.println("myMsg:"+msg);
2:在application的应用。
xml代码段:
ActivityInfo info=this.getPackageManager()
.getActivityInfo(getComponentName(),
PackageManager.GET_META_DATA);
String msg=info.metaData.getString("myMsg");
System.out.println("myMsg:"+msg);
<application...>
<meta-data android:value="hello my application" android:name="myMsg"></meta-data>
</application>
java代码段:
<application...>
<meta-data android:value="hello my application" android:name="myMsg"></meta-data>
</application>
ApplicationInfo appInfo = this.getPackageManager()
.getApplicationInfo(getPackageName(),
PackageManager.GET_META_DATA);
String msg=appInfo.metaData.getString("myMsg");
System.out.println("myMsg:"+msg);
3:在service的应用。
xml代码段:
ApplicationInfo appInfo = this.getPackageManager()
.getApplicationInfo(getPackageName(),
PackageManager.GET_META_DATA);
String msg=appInfo.metaData.getString("myMsg");
System.out.println("myMsg:"+msg);
<service android:name="MetaDataService">
<meta-data android:value="hello my service" android:name="myMsg"></meta-data>
</service>
java代码段:
<service android:name="MetaDataService">
<meta-data android:value="hello my service" android:name="myMsg"></meta-data>
</service>
ComponentName cn=new ComponentName(this, MetaDataService.class);
ServiceInfo info=this.getPackageManager()
.getServiceInfo(cn, PackageManager.GET_META_DATA);
String msg=info.metaData.getString("myMsg");
System.out.println("myMsg:"+msg);
4: 在receiver的应用。
xml代码段:
ComponentName cn=new ComponentName(this, MetaDataService.class);
ServiceInfo info=this.getPackageManager()
.getServiceInfo(cn, PackageManager.GET_META_DATA);
String msg=info.metaData.getString("myMsg");
System.out.println("myMsg:"+msg);
<receiver android:name="MetaDataReceiver">
<meta-data android:value="hello my receiver" android:name="myMsg"></meta-data>
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE"></action>
</intent-filter>
</receiver>
java代码段:
<receiver android:name="MetaDataReceiver">
<meta-data android:value="hello my receiver" android:name="myMsg"></meta-data>
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE"></action>
</intent-filter>
</receiver>
ComponentName cn=new ComponentName(context, MetaDataReceiver.class);
ActivityInfo info=context.getPackageManager()
.getReceiverInfo(cn, PackageManager.GET_META_DATA);
String msg=info.metaData.getString("myMsg");
System.out.println("myMsg:"+msg);
有了以上了解这个service的注册也了解了
ComponentName cn=new ComponentName(context, MetaDataReceiver.class);
ActivityInfo info=context.getPackageManager()
.getReceiverInfo(cn, PackageManager.GET_META_DATA);
String msg=info.metaData.getString("myMsg");
System.out.println("myMsg:"+msg);
/BubbleLiveWallPaper/res/xml/bubblelivewallpaper.xml
<?xml version="1.0" encoding="UTF-8"?>
<wallpaper
xmlns:android="http://schemas.android.com/apk/res/android"
android:thumbnail="@drawable/appicon"
android:description="@string/app_name"
/>
android:thumbnail="@drawable/appicon"的图标
android:description="@string/app_name"的用名
具体什么意思看官方api吧
<?xml version="1.0" encoding="UTF-8"?>
<wallpaper
xmlns:android="http://schemas.android.com/apk/res/android"
android:thumbnail="@drawable/appicon"
android:description="@string/app_name"
/>
android:thumbnail="@drawable/appicon"的图标
android:description="@string/app_name"的用名