android Launcher基础知识
1、launcher最简单实例
launcher,也就是android的桌面应用程序。下图是android2.3的launcher应用程序:
接下来我们要开发一个自己的launcher,使其替代系统的默认launcher。
怎样使我们的应用程序成为一个launcher?
下面我们就新建一个叫做MyHome的工程,具体步骤略。创建完工程后整个目录结构如下图:
现在我们的AndroidManifest.xml文件这样的:
- <?xmlversion="1.0"encoding="utf-8"?>
- <manifestxmlns:android="http://schemas.android.com/apk/res/android"
- package="org.bangchui.myhome"
- android:versionCode="1"
- android:versionName="1.0">
- <applicationandroid:icon="@drawable/icon"android:label="@string/app_name">
- <activityandroid:name=".MyHome"
- android:label="@string/app_name">
- <intent-filter>
- <actionandroid:name="android.intent.action.MAIN"/>
- <categoryandroid:name="android.intent.category.LAUNCHER"/>
- </intent-filter>
- </activity>
- </application>
- </manifest>
</intent-filter>里面的内容。
下面我们在其中添加上以下两行:
[java] view plain copy
- <categoryandroid:name="android.intent.category.HOME"/>
- <categoryandroid:name="android.intent.category.DEFAULT"/>
- <?xmlversion="1.0"encoding="utf-8"?>
- <manifestxmlns:android="http://schemas.android.com/apk/res/android"
- package="org.bangchui.myhome"
- android:versionCode="1"
- android:versionName="1.0">
- <applicationandroid:icon="@drawable/icon"android:label="@string/app_name">
- <activityandroid:name=".MyHome"
- android:label="@string/app_name">
- <intent-filter>
- <actionandroid:name="android.intent.action.MAIN"/>
- <categoryandroid:name="android.intent.category.LAUNCHER"/>
- <categoryandroid:name="android.intent.category.HOME"/>
- <categoryandroid:name="android.intent.category.DEFAULT"/>
- </intent-filter>
- </activity>
- </application>
- </manifest>
我们看到了,我们开发的Myhome跟Launcher出现在了一起。
重启模拟器,我们看到我们自己的程序已经可以作为home来运行了。
ok。 第一步完成了:把我们的应用程序作为home。
总结一下:要把我们的应用程序作为home,只需要在AndroidManifest.xml中添加:
- <categoryandroid:name="android.intent.category.HOME"/>
- <categoryandroid:name="android.intent.category.DEFAULT"/>
2、列出安装的应用程序
列出已经安装的应用程序是作为launcher必不可少的功能。下面我们就讲解怎样将应用程序列出来。程序运行后的样子如下:
一. 修改main.xml,在其中添加一个GridView用来显示应用程序列表。
修改后如下:
- <?xmlversion="1.0"encoding="utf-8"?>
- <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"android:layout_width="fill_parent"
- android:layout_height="fill_parent">
- <GridViewandroid:layout_width="match_parent"
- android:id="@+id/apps_list"
- android:numColumns="4"
- android:layout_height="wrap_content">
- </GridView>
- </LinearLayout>
我们写一个叫做loadApps的方法将活得的应用程序列表放到private List<ResolveInfo> mApps; 中,如下:
[java] view plain copy
- privatevoidloadApps(){
- IntentmainIntent=newIntent(Intent.ACTION_MAIN,null);
- mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
- mApps=getPackageManager().queryIntentActivities(mainIntent,0);
- }
最后整个Activity的代码如下
[java] view plain copy
- packageorg.bangchui.myhome;
- importjava.util.List;
- importandroid.app.Activity;
- importandroid.content.Intent;
- importandroid.content.pm.ResolveInfo;
- importandroid.os.Bundle;
- importandroid.view.View;
- importandroid.view.ViewGroup;
- importandroid.widget.BaseAdapter;
- importandroid.widget.GridView;
- importandroid.widget.ImageView;
- publicclassMyHomeextendsActivity
- {
- GridViewmGrid;
- /**Calledwhentheactivityisfirstcreated.*/
- @OverridepublicvoidonCreate(BundlesavedInstanceState){
- super.onCreate(savedInstanceState);
- loadApps();
- setContentView(R.layout.main);
- mGrid=(GridView)findViewById(R.id.apps_list);
- mGrid.setAdapter(newAppsAdapter());
- }
- privateList<ResolveInfo>mApps;
- privatevoidloadApps(){
- IntentmainIntent=newIntent(Intent.ACTION_MAIN,null);
- mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
- mApps=getPackageManager().queryIntentActivities(mainIntent,0);
- }
- publicclassAppsAdapterextendsBaseAdapter
- {
- publicAppsAdapter(){}
- publicViewgetView(intposition,ViewconvertView,ViewGroupparent){
- ImageViewi;
- if(convertView==null){
- i=newImageView(MyHome.this);
- i.setScaleType(ImageView.ScaleType.FIT_CENTER);
- i.setLayoutParams(newGridView.LayoutParams(50,50));
- }else{
- i=(ImageView)convertView;
- }
- ResolveInfoinfo=mApps.get(position);
- i.setImageDrawable(info.activityInfo.loadIcon(getPackageManager()));
- returni;
- }
- publicfinalintgetCount(){
- returnmApps.size();
- }
- publicfinalObjectgetItem(intposition){
- returnmApps.get(position);
- }
- publicfinallonggetItemId(intposition){
- returnposition;
- }
- }
- }
1. 监听GridView的onItemClick事件
设置一个监听器是为了当gridView的某项被点击时,会有一个回调函数通知我们。
我们调用mGrid.setOnItemClickListener(listener); 设置一个监听器
mGrid.setOnItemClickListener(listener)中的listener是一个接口,其类型为:android.widget.AdapterView.OnItemClickListener,如下图所示:
下面我们new一个android.widget.AdapterView.OnItemClickListener类型的对象作为参数。我们直接使用eclipde的自动补全功能来完成OnItemClickListener 的定义: [java] view plain copy
- privateOnItemClickListenerlistener=newOnItemClickListener()
- {
- @OverridepublicvoidonItemClick(AdapterView<?>parent,Viewview,intposition,longid){}
- };
parent 略
view 被点击的view
position 被点击项的位置
id 被点击项的id
2.启动被点击应用的activity
一般来讲,我们根据position即可知道被点击的项目是哪一项了。现在我们根据被点击的项目,取出对应的应用程序数据(主要是其中的主activity),然后启动activity。用下面代码实现: [java] view plain copy
- @OverridepublicvoidonItemClick(AdapterView<?>parent,Viewview,intposition,longid){
- ResolveInfoinfo=mApps.get(position);
- //该应用的包名Stringpkg=info.activityInfo.packageName;
- //应用的主activity类Stringcls=info.activityInfo.name;
- ComponentNamecomponet=newComponentName(pkg,cls);
- Intenti=newIntent();
- i.setComponent(componet);
- startActivity(i);
- }
现在整个类代码如下:
[java] view plain copy
- packageorg.bangchui.myhome;
- importjava.util.List;
- importandroid.app.Activity;
- importandroid.content.ComponentName;
- importandroid.content.Intent;
- importandroid.content.pm.ResolveInfo;
- importandroid.os.Bundle;
- importandroid.view.View;
- importandroid.view.ViewGroup;
- importandroid.widget.AdapterView;
- importandroid.widget.BaseAdapter;
- importandroid.widget.GridView;
- importandroid.widget.ImageView;
- importandroid.widget.AdapterView.OnItemClickListener;
- publicclassMyHomeextendsActivity{
- privateList<ResolveInfo>mApps;
- GridViewmGrid;
- privateOnItemClickListenerlistener=newOnItemClickListener(){
- @Override
- publicvoidonItemClick(AdapterView<?>parent,Viewview,intposition,longid){
- ResolveInfoinfo=mApps.get(position);
- //该应用的包名
- Stringpkg=info.activityInfo.packageName;
- //应用的主activity类
- Stringcls=info.activityInfo.name;
- ComponentNamecomponet=newComponentName(pkg,cls);
- Intenti=newIntent();
- i.setComponent(componet);
- startActivity(i);
- }
- };
- /**Calledwhentheactivityisfirstcreated.*/
- @Override
- publicvoidonCreate(BundlesavedInstanceState){
- super.onCreate(savedInstanceState);
- loadApps();
- setContentView(R.layout.main);
- mGrid=(GridView)findViewById(R.id.apps_list);
- mGrid.setAdapter(newAppsAdapter());
- mGrid.setOnItemClickListener(listener);
- }
- privatevoidloadApps(){
- IntentmainIntent=newIntent(Intent.ACTION_MAIN,null);
- mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
- mApps=getPackageManager().queryIntentActivities(mainIntent,0);
- }
- publicclassAppsAdapterextendsBaseAdapter{
- publicAppsAdapter(){
- }
- publicViewgetView(intposition,ViewconvertView,ViewGroupparent){
- ImageViewi;
- if(convertView==null){
- i=newImageView(MyHome.this);
- i.setScaleType(ImageView.ScaleType.FIT_CENTER);
- i.setLayoutParams(newGridView.LayoutParams(50,50));
- }else{
- i=(ImageView)convertView;
- }
- ResolveInfoinfo=mApps.get(position);
- i.setImageDrawable(info.activityInfo.loadIcon(getPackageManager()));
- returni;
- }
- publicfinalintgetCount(){
- returnmApps.size();
- }
- publicfinalObjectgetItem(intposition){
- returnmApps.get(position);
- }
- publicfinallonggetItemId(intposition){
- returnposition;
- }
- }
- }
我们要达到这样的效果:点击“add widget” 后弹出widget列表,之后选择一个widget后显示在界面上,如下:
1. 获取widget信息
获取widget其实非常简单,我们只需要发送一个请求到系统,系统就会打开widget的列表,然后我们选择一个即可。代码如下:
- voidaddWidget(){
- intappWidgetId=mAppWidgetHost.allocateAppWidgetId();
- IntentpickIntent=newIntent(AppWidgetManager.ACTION_APPWIDGET_PICK);
- pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,appWidgetId);
- //startthepickactivity
- startActivityForResult(pickIntent,[b]REQUEST_PICK_APPWIDGET[/b]);
- }
当选择一个widget后会通过onActivityResult 通知到activity,widget的信息被包含在 Intent data中,详情看代码注释 [java] view plain copy
- @OverrideprotectedvoidonActivityResult(intrequestCode,intresultCode,Intentdata){
- //ThepatternusedhereisthatauserPICKsaspecificapplication,
- //which,dependingonthetarget,mightneedtoCREATEtheactual
- //target.
- //Forexample,theuserwouldPICK_SHORTCUTfor"Musicplaylist",and
- //we
- //launchovertotheMusicapptoactuallyCREATE_SHORTCUT.
- if(resultCode==RESULT_OK){
- switch(requestCode){
- caseREQUEST_PICK_APPWIDGET:
- addAppWidget(data);
- break;
- caseREQUEST_CREATE_APPWIDGET:
- completeAddAppWidget(data);
- break;
- }
- }
- }
- voidaddAppWidget(Intentdata){
- //TODO:catchbadwidgetexceptionwhensent
- intappWidgetId=data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,-1);
- AppWidgetProviderInfoappWidget=mAppWidgetManager.getAppWidgetInfo(appWidgetId);
- //widget包含设置信息不为空,则启动widget的设置界面
- if(appWidget.configure!=null){
- //Launchovertoconfigurewidget,ifneeded
- Intentintent=newIntent(
- AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
- intent.setComponent(appWidget.configure);
- intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,appWidgetId);
- startActivityForResultSafely(intent,REQUEST_CREATE_APPWIDGET);
- }else{
- //widget包含设置信息为空,直接添加widget到layout中
- //Otherwisejustaddit
- onActivityResult(REQUEST_CREATE_APPWIDGET,Activity.RESULT_OK,data);
- }
- }
- voidstartActivityForResultSafely(Intentintent,intrequestCode){
- try{
- startActivityForResult(intent,requestCode);
- }catch(ActivityNotFoundExceptione){
- Toast.makeText(this,"activity_not_found",Toast.LENGTH_SHORT).show();
- }catch(SecurityExceptione){
- Toast.makeText(this,"activity_not_found",Toast.LENGTH_SHORT).show();
- }
- }
- /***添加widget信息到layout中
- **@paramdata包含了widget的信息*/
- privatevoidcompleteAddAppWidget(Intentdata){
- Bundleextras=data.getExtras();
- intappWidgetId=extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID,-1);
- Log.d(TAG,"dumpingextrascontent="+extras.toString());
- AppWidgetProviderInfoappWidgetInfo=mAppWidgetManager.getAppWidgetInfo(appWidgetId);
- //Performactualinflationbecausewe'relive
- synchronized(mLock){
- //获取显示widget的view
- mHostView=mAppWidgetHost.createView(this,appWidgetId,appWidgetInfo);
- mHostView.setAppWidget(appWidgetId,appWidgetInfo);
- //将获取的view添加早layout中
- LayoutParamslp=newLinearLayout.LayoutParams(appWidgetInfo.minWidth,appWidgetInfo.minHeight);
- mainLayout.addView(mHostView,lp);
- mHostView.requestLayout();
- }
- }
显示壁纸也是launcher必不可少的功能,下面我们看看如何让我们开发的launcher来显示壁纸。
新建一个叫做ShowWallpaper的工程,具体步骤略。
一. 显示壁纸
要在我们的activity里显示一个壁纸非常简单(包括动态壁纸也如此),我们只需要定义一个theme使其继承自android:Theme.Wallpaper,然后在activity中使用这个theme就ok了。
在res/valuse下面增加一个xml文件,其名称为styles.xml ,内容如下:
- <resources>
- <stylename="Theme"parent="android:Theme.Wallpaper">
- <!--windowNoTitle设置为true,去掉标题栏-->
- <itemname="android:windowNoTitle">true</item>
- </style>
- </resources>
下面在AndroidManifest.xml中使用这个theme,如下代码所示:
[html] view plain copy- <?xmlversion="1.0"encoding="utf-8"?>
- <manifestxmlns:android="http://schemas.android.com/apk/res/android"
- package="com.test"
- android:versionCode="1"
- android:versionName="1.0">
- <applicationandroid:icon="@drawable/icon"android:label="@string/app_name">
- <activityandroid:name=".ShowWallpaper"
- android:theme="@style/Theme"
- android:label="@string/app_name">
- <intent-filter>
- <actionandroid:name="android.intent.action.MAIN"/>
- <categoryandroid:name="android.intent.category.LAUNCHER"/>
- </intent-filter>
- </activity>
- </application>
- </manifest>
用代码设置壁纸也是非常地简单的事,我们只需要向系统发送一个“设置请求”就足够了,其它的事情系统处理。
用下面代码表示:
[java] view plain copy- publicvoidonSetWallpaper(Viewview){
- //生成一个设置壁纸的请求
- finalIntentpickWallpaper=newIntent(Intent.ACTION_SET_WALLPAPER);
- Intentchooser=Intent.createChooser(pickWallpaper,"chooser_wallpaper");
- //发送设置壁纸的请求
- startActivity(chooser);
- }
[html] view plain copy
- <?xmlversion="1.0"encoding="utf-8"?>
- <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical">
- <TextView
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="@string/hello"/>
- <Button
- android:id="@+id/button1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="setWallpaper"
- android:onClick="onSetWallpaper"/>
- </LinearLayout>
设置壁纸后:
参考资料:
更多相关文章
- Android代码内存优化建议-OnTrimMemory优化
- android.uid.system Android中如何修改系统时间(应用程序获得系
- 如何修改Android应用程序能够使用的默认最大内存值
- Gears Android WIFI/基站定位源代码分析
- 安卓学习(初)第三章(2)(《第一行代码》)
- Android应用程序中Manifest.java文件的介绍
- Android 2.3禁止系统弹出应用程序强制退出对话框