android Launcher基礎知識

來源:互聯網
上載者:User

        本文將www.bangchui.org網路中的《android手把手教你開發launcher》系列文章進行了整理。這篇文章對lancher的準系統點的實現做了簡單介紹,看完後會對lancher有比較深刻的認識。

1、launcher最簡單一實例

launcher,也就是android的傳統型應用程式。是android2.3的launcher應用程式:

接下來我們要開發一個自己的launcher,使其替代系統的預設launcher。
怎樣使我們的應用程式成為一個launcher?

下面我們就建立一個叫做MyHome的工程,具體步驟略。建立完工程後整個目錄結構如:

現在我們的AndroidManifest.xml檔案這樣的:

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"      package="org.bangchui.myhome"      android:versionCode="1"      android:versionName="1.0">     <application android:icon="@drawable/icon" android:label="@string/app_name">        <activity android:name=".MyHome"                  android:label="@string/app_name">            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>     </application></manifest>

請注意<intent-filter>
</intent-filter>裡面的內容。
下面我們在其中添加上以下兩行:

<category android:name="android.intent.category.HOME" /><category android:name="android.intent.category.DEFAULT" />

此時AndroidManifest.xml檔案是這樣:

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"      package="org.bangchui.myhome"      android:versionCode="1"      android:versionName="1.0">         <application android:icon="@drawable/icon" android:label="@string/app_name">         <activity android:name=".MyHome"                  android:label="@string/app_name">             <intent-filter>                 <action android:name="android.intent.action.MAIN" />                 <category android:name="android.intent.category.LAUNCHER" />                 <category android:name="android.intent.category.HOME" />                 <category android:name="android.intent.category.DEFAULT" />             </intent-filter>         </activity>       </application> </manifest>

此時運行程式,我們看不到任何特別之處。當按下home鍵時(模擬器上按下home會調出案頭應用),程式

我們看到了,我們開發的Myhome跟Launcher出現在了一起。 
重啟模擬器,我們看到我們自己的程式已經可以作為home來運行了。
ok。 第一步完成了:把我們的應用程式作為home。
總結一下:要把我們的應用程式作為home,只需要在AndroidManifest.xml中添加:

 <category android:name="android.intent.category.HOME" /> <category android:name="android.intent.category.DEFAULT" />

2、列出安裝的應用程式

        列出已經安裝的應用程式是作為launcher必不可少的功能。下面我們就講解怎樣將應用程式列出來。程式運行後的樣子如下:

一. 修改main.xml,在其中添加一個GridView用來顯示應用程式列表。
修改後如下:

<?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">            <GridView android:layout_width="match_parent"             android:id="@+id/apps_list"            android:numColumns="4"            android:layout_height="wrap_content">        </GridView></LinearLayout>

二 . 通過PackageManager的api 查詢已經安裝的apk
我們寫一個叫做loadApps的方法將活得的應用程式列表放到private List<ResolveInfo> mApps; 中,如下:

private void loadApps() {             Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);             mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);               mApps = getPackageManager().queryIntentActivities(mainIntent, 0);         }

三. 實現用於顯示Gridview的Adapter,使其顯示獲得的應用程式列表
最後整個Activity的代碼如下

package org.bangchui.myhome;     import java.util.List;     import android.app.Activity; import android.content.Intent; import android.content.pm.ResolveInfo; import android.os.Bundle; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.GridView; import android.widget.ImageView;     public class MyHome extends Activity {       GridView mGrid;           /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);                   loadApps();         setContentView(R.layout.main);         mGrid = (GridView) findViewById(R.id.apps_list);         mGrid.setAdapter(new AppsAdapter());     }                 private List<ResolveInfo> mApps;         private void loadApps() {         Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);         mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);            mApps = getPackageManager().queryIntentActivities(mainIntent, 0);    }         public class AppsAdapter extends BaseAdapter {         public AppsAdapter() {         }             public View getView(int position, View convertView, ViewGroup parent) {             ImageView i;                 if (convertView == null) {                 i = new ImageView(MyHome.this);                 i.setScaleType(ImageView.ScaleType.FIT_CENTER);                 i.setLayoutParams(new GridView.LayoutParams(50, 50));             } else {                 i = (ImageView) convertView;             }                 ResolveInfo info = mApps.get(position);            i.setImageDrawable(info.activityInfo.loadIcon(getPackageManager()));                 return i;         }                 public final int getCount() {            return mApps.size();         }             public final Object getItem(int position) {             return mApps.get(position);         }             public final long getItemId(int position) {             return position;         }     } }

3、啟動安裝的應用程式
1. 監聽GridView的onItemClick事件
設定一個監聽器是為了當gridView的某項被點擊時,會有一個回呼函數通知我們。
我們調用mGrid.setOnItemClickListener(listener); 設定一個監聽器
mGrid.setOnItemClickListener(listener)中的listener是一個介面,其類型為:android.widget.AdapterView.OnItemClickListener,如所示:

下面我們new一個android.widget.AdapterView.OnItemClickListener類型的對象作為參數。我們直接使用eclipde的自動補全功能來完成OnItemClickListener 的定義:

private OnItemClickListener listener = new OnItemClickListener() {@Override public void onItemClick(AdapterView<?> parent, View view, int position,long id) {}};

介面OnItemClickListener 中有一個方法叫做onItemClick,我們實現它即可。下面我對onItemClick的幾個參數略作說明:
parent     略
view          被點擊的view
position     被點擊項的位置
id             被點擊項的id
2.啟動被點擊應用的activity
一般來講,我們根據position即可知道被點擊的項目是哪一項了。現在我們根據被點擊的項目,取出對應的應用程式資料(主要是其中的主activity),然後啟動activity。用下面代碼實現:

@Override public void onItemClick(AdapterView<?> parent, View view, int position,long id) {          ResolveInfo info = mApps.get(position);                        //該應用的包名            String pkg = info.activityInfo.packageName;            //應用的主activity類            String cls = info.activityInfo.name;                        ComponentName componet = new ComponentName(pkg, cls);                        Intent i = new Intent();            i.setComponent(componet);            startActivity(i);        }

例如,我們點擊計算機時,啟動了計算機,如:

現在整個類代碼如下:

package org.bangchui.myhome;import java.util.List;import android.app.Activity;import android.content.ComponentName;import android.content.Intent;import android.content.pm.ResolveInfo;import android.os.Bundle;import android.view.View;import android.view.ViewGroup;import android.widget.AdapterView;import android.widget.BaseAdapter;import android.widget.GridView;import android.widget.ImageView;import android.widget.AdapterView.OnItemClickListener;public class MyHome extends Activity {    private List<ResolveInfo> mApps;    GridView mGrid;    private OnItemClickListener listener = new OnItemClickListener() {        @Override        public void onItemClick(AdapterView<?> parent, View view, int position,long id) {            ResolveInfo info = mApps.get(position);                        //該應用的包名            String pkg = info.activityInfo.packageName;            //應用的主activity類            String cls = info.activityInfo.name;                        ComponentName componet = new ComponentName(pkg, cls);                        Intent i = new Intent();            i.setComponent(componet);            startActivity(i);        }    };    /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        loadApps();        setContentView(R.layout.main);        mGrid = (GridView) findViewById(R.id.apps_list);        mGrid.setAdapter(new AppsAdapter());        mGrid.setOnItemClickListener(listener);    }    private void loadApps() {        Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);        mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);        mApps = getPackageManager().queryIntentActivities(mainIntent, 0);    }    public class AppsAdapter extends BaseAdapter {        public AppsAdapter() {        }        public View getView(int position, View convertView, ViewGroup parent) {            ImageView i;            if (convertView == null) {                i = new ImageView(MyHome.this);                i.setScaleType(ImageView.ScaleType.FIT_CENTER);                i.setLayoutParams(new GridView.LayoutParams(50, 50));            } else {                i = (ImageView) convertView;            }            ResolveInfo info = mApps.get(position);            i.setImageDrawable(info.activityInfo.loadIcon(getPackageManager()));            return i;        }        public final int getCount() {            return mApps.size();        }        public final Object getItem(int position) {            return mApps.get(position);        }        public final long getItemId(int position) {            return position;        }    }}

4、顯示widget

我們要達到這樣的效果:點擊“add widget” 後彈出widget列表,之後選擇一個widget後顯示在介面上,如下:

1. 擷取widget資訊
擷取widget其實非常簡單,我們只需要發送一個請求到系統,系統就會開啟widget的列表,然後我們選擇一個即可。代碼如下:

void addWidget() {         int appWidgetId = mAppWidgetHost.allocateAppWidgetId();         Intent pickIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_PICK);         pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);         // start the pick activity         startActivityForResult(pickIntent, [b]REQUEST_PICK_APPWIDGET[/b]);     }

2. 添加widget的view到layout中
當選擇一個widget後會通過onActivityResult 通知到activity,widget的資訊被包含在 Intent data中,詳情看代碼注釋

@Override   protected void onActivityResult(int requestCode, int resultCode, Intent data) {         // The pattern used here is that a user PICKs a specific application,         // which, depending on the target, might need to CREATE the actual         // target.           // For example, the user would PICK_SHORTCUT for "Music playlist", and         // we         // launch over to the Music app to actually CREATE_SHORTCUT.           if (resultCode == RESULT_OK) {             switch (requestCode) {             case REQUEST_PICK_APPWIDGET:                 addAppWidget(data);                 break;             case REQUEST_CREATE_APPWIDGET:                 completeAddAppWidget(data);                 break;               }         }     }       void addAppWidget(Intent data) {         // TODO: catch bad widget exception when sent         int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);         AppWidgetProviderInfo appWidget = mAppWidgetManager.getAppWidgetInfo(appWidgetId);           //widget 包含設定資訊不為空白,則啟動widget的設定介面        if (appWidget.configure != null) {             // Launch over to configure widget, if needed             Intent intent = new Intent(                     AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);             intent.setComponent(appWidget.configure);             intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);               startActivityForResultSafely(intent, REQUEST_CREATE_APPWIDGET);         } else {         //    widget 包含設定資訊為空白,直接添加widget到layout中            // Otherwise just add it             onActivityResult(REQUEST_CREATE_APPWIDGET, Activity.RESULT_OK, data);         }     }       void startActivityForResultSafely(Intent intent, int requestCode) {         try {             startActivityForResult(intent, requestCode);         } catch (ActivityNotFoundException e) {             Toast.makeText(this, "activity_not_found", Toast.LENGTH_SHORT).show();         } catch (SecurityException e) {             Toast.makeText(this, "activity_not_found", Toast.LENGTH_SHORT).show();         }     } /**      * 添加widget資訊到layout中        * * @param data 包含了widget的資訊      */    private void completeAddAppWidget(Intent data) {         Bundle extras = data.getExtras();         int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);           Log.d(TAG, "dumping extras content=" + extras.toString());           AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);           // Perform actual inflation because we're live         synchronized (mLock) {                           //擷取顯示widget的view             mHostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);             mHostView.setAppWidget(appWidgetId, appWidgetInfo);               //將擷取的view添加早layout中            LayoutParams lp = new LinearLayout.LayoutParams(appWidgetInfo.minWidth, appWidgetInfo.minHeight);             mainLayout.addView(mHostView, lp);               mHostView.requestLayout();         }    }

5、顯示和設定壁紙

顯示壁紙也是launcher必不可少的功能,下面我們看看如何讓我們開發的launcher來顯示壁紙。
建立一個叫做ShowWallpaper的工程,具體步驟略。
一. 顯示壁紙
要在我們的activity裡顯示一個壁紙非常簡單(包括動態壁紙也如此),我們只需要定義一個theme使其繼承自android:Theme.Wallpaper,然後在activity中使用這個theme就ok了。
在res/valuse下面增加一個xml檔案,其名稱為styles.xml ,內容如下:

<resources>     <style name="Theme" parent="android:Theme.Wallpaper">         <!-- windowNoTitle設定為true,去掉標題列 -->        <item name="android:windowNoTitle">true</item>     </style> </resources>

此時整個工程的結果如下:

下面在AndroidManifest.xml中使用這個theme,如下代碼所示:

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"      package="com.test"      android:versionCode="1"      android:versionName="1.0">     <application android:icon="@drawable/icon" android:label="@string/app_name">         <activity android:name=".ShowWallpaper"                     android:theme="@style/Theme"                  android:label="@string/app_name">             <intent-filter>                 <action android:name="android.intent.action.MAIN" />                 <category android:name="android.intent.category.LAUNCHER" />              </intent-filter>          </activity>         </application></manifest>

好了,運行程式,可以看到壁紙的顯示效果了:(顯示的是預設定的動態壁紙:星系)

用代碼設定壁紙也是非常地簡單的事,我們只需要向系統發送一個“佈建要求”就足夠了,其它的事情系統處理。

用下面代碼錶示:

public void onSetWallpaper(View view) {                         //產生一個設定壁紙的請求              final Intent pickWallpaper = new Intent(Intent.ACTION_SET_WALLPAPER);                 Intent chooser = Intent.createChooser(pickWallpaper,"chooser_wallpaper");                 //發送設定壁紙的請求                 startActivity(chooser);     }

為了調用上面這段代碼,我們在xml中添加一個button,並設定回呼函數,如:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns: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手把手教你開發launcher(一)
android手把手教你開發launcher(二)
android手把手教你開發launcher(三 )
android手把手教你開發launcher(四 )
android手把手教你開發launcher(五 )

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.