Android Launcher 研究學習

來源:互聯網
上載者:User

標籤:des   android   style   blog   http   io   color   ar   os   

Launcher是系統啟動後第一個啟動的程式,是其它應用程式的入口,也就是我們的手機程式的傳統型程式;

一、Launcher的定義及構成:

<1>通過查看官方提供的Launcher源碼可以知道其實Launcher也是一個Activity,不過它的intent-fliter有點特殊;

        <activity            android:name="Launcher"            android:launchMode="singleTask"            android:clearTaskOnLaunch="true"            android:stateNotNeeded="true"            android:theme="@android:style/Theme.Wallpaper.NoTitleBar"            android:screenOrientation="nosensor"            android:windowSoftInputMode="stateUnspecified|adjustPan">            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.HOME"/>                <category android:name="android.intent.category.DEFAULT" />                <category android:name="android.intent.category.MONKEY" />            </intent-filter>        </activity>

Launcher的intent-filter中,action為intent.action.MAIN,表示該Activity是程式的主入口,但是它的category是category.HOME,和一般的app不一樣,category.HOME則標識了這個Activity是一個Launcher,其實就是對應的按下HOME鍵所跳轉到的Activity,也就是我們的案頭;

下面我們再來看一下一個普通的App的程式主入口Activity的配置:

<action android:name="android.intent.action.MAIN" /> 表示該類是程式主入口;<category android:name="android.intent.category.LAUNCHER" /> 

category.LAUNCHER表示該Activity在Launcher上可見,所以這一個Activity會被添加到Launcher;

<2>Launcher構成:
HomeScreen(WorkSpace+HotSeats),Shortcut(捷徑),LiveFolder(檔案夾),AppWidget(視窗小組件),WallPaper(壁紙);
AllAppList:

下面我們就來分別研究探討這四個元素

1、Shortcut
在Launcher的設定檔裡面有這樣一個廣播接收者用於監聽添加捷徑

        <receiver            android:name=".InstallShortcutReceiver"            android:permission="com.android.launcher.permission.INSTALL_SHORTCUT">            <intent-filter>                <action android:name="com.android.launcher.action.INSTALL_SHORTCUT" />            </intent-filter>        </receiver>

查看InstallShortcutReceiver的源碼

public class InstallShortcutReceiver extends BroadcastReceiver {    private static final String ACTION_INSTALL_SHORTCUT =            "com.android.launcher.action.INSTALL_SHORTCUT";    private final int[] mCoordinates = new int[2];    public void onReceive(Context context, Intent data) {        if (!ACTION_INSTALL_SHORTCUT.equals(data.getAction())) {            return;        }        int screen = Launcher.getScreen();        if (!installShortcut(context, data, screen)) {            // The target screen is full, let‘s try the other screens            for (int i = 0; i < Launcher.SCREEN_COUNT; i++) {                if (i != screen && installShortcut(context, data, i)) break;            }        }    }}

從上面的核心代碼可以看出,在BroadcastReceiver接收到INSTALL_SHORTCUT廣播之後,會嘗試在當前屏添加捷徑,如果當前屏滿了,則會嘗試將捷徑添加到其它屏;因此,當我們想添加一個捷徑到螢幕的時候,其實就很簡單了,發送一個廣播,並且設定它的Action為INSTALL_SHORTCUT即可;但是,需要注意的是如果僅僅設定Action是不夠的,因為僅僅這樣做會重複添加捷徑,如果想不重複添加,還得做一些設定,詳情參考這裡;

2、LiveFolder

在Launcher.java檔案中,找到添加LiveFolder的入口

                    // Insert extra item to handle inserting folder                    Bundle bundle = new Bundle();                    ArrayList<String> shortcutNames = new ArrayList<String>();                    shortcutNames.add(res.getString(R.string.group_folder));                    bundle.putStringArrayList(Intent.EXTRA_SHORTCUT_NAME, shortcutNames);                    ArrayList<ShortcutIconResource> shortcutIcons = new ArrayList<ShortcutIconResource>();                    shortcutIcons.add(ShortcutIconResource.fromContext(Launcher.this, R.drawable.ic_launcher_folder));                    bundle.putParcelableArrayList(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, shortcutIcons);                    Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY);                    pickIntent.putExtra(Intent.EXTRA_INTENT, new Intent(LiveFolders.ACTION_CREATE_LIVE_FOLDER));                    pickIntent.putExtra(Intent.EXTRA_TITLE, getText(R.string.title_select_live_folder));                    pickIntent.putExtras(bundle);                    startActivityForResult(pickIntent, REQUEST_PICK_LIVE_FOLDER);

當我們長按案頭之後,選擇添加檔案夾,則會執行上面這段代碼,在這裡會先建立好一個空檔案夾;

    void addLiveFolder(Intent intent) { // RESULT_PICK_LIVE_FOLDER        // Handle case where user selected "Folder"        String folderName = getResources().getString(R.string.group_folder);        String shortcutName = intent.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);        if (folderName != null && folderName.equals(shortcutName)) {            addFolder(!mDesktopLocked);        } else {            startActivityForResult(intent, REQUEST_CREATE_LIVE_FOLDER);        }    }

完成添加

    private void completeAddLiveFolder(Intent data, CellLayout.CellInfo cellInfo,            boolean insertAtFirst) { // REQUEST_CREATE_LIVE_FOLDER        cellInfo.screen = mWorkspace.getCurrentScreen();        if (!findSingleSlot(cellInfo)) return;        final LiveFolderInfo info = addLiveFolder(this, data, cellInfo, false);        if (!mRestoring) {            sModel.addDesktopItem(info);            final View view = LiveFolderIcon.fromXml(R.layout.live_folder_icon, this,                (ViewGroup) mWorkspace.getChildAt(mWorkspace.getCurrentScreen()), info);            mWorkspace.addInCurrentScreen(view, cellInfo.cellX, cellInfo.cellY, 1, 1, insertAtFirst);        } else if (sModel.isDesktopLoaded()) {            sModel.addDesktopItem(info);        }    }

3、AppWidget:AppWidgetProvider用來在HOME頁面顯示外掛程式

實現步驟:
1、為AppWidget提供一個元布局檔案AppWigdetProvider_Provider.xml,用來顯示Widget的介面。
2、建立一個類繼承自AppWidgetProvider,並覆寫裡面的相關的方法並且註冊到設定檔。
3、為WidgetProvider建立一個引用的布局檔案。

代碼如下:

1、在res/xml/檔案夾下建立AppWigdetProvider_Provider.xml檔案

<?xml version="1.0" encoding="utf-8"?><appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"  android:initialLayout="@layout/main"  <!-- android:initialLayout 設定引用的布局檔案 -->  android:minHeight="50dip"  android:minWidth="50dip"  android:updatePeriodMillis="5000" > <!-- 設定更新時間,單位為毫秒 --></appwidget-provider>

2、修改MainActivity繼承自AppWidgetProvider並覆寫裡面的一些方法,實際上AppWidgetProvider就是一個BroadcastReceiver;

public class MainActivity extends AppWidgetProvider {    @Override    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {        super.onUpdate(context, appWidgetManager, appWidgetIds);        Timer timer = new Timer();        timer.scheduleAtFixedRate(new LYTimeTask(context, appWidgetManager), 1, 50000);    }    private class LYTimeTask extends TimerTask {        RemoteViews remoteViews;        AppWidgetManager appWidgetManager;        ComponentName widget;        @Override        public void run() {            Date date = new Date();            Calendar calendar = new GregorianCalendar(2013, 07, 24);            long days = (calendar.getTimeInMillis() - date.getTime()) / 1000 / 86400;            remoteViews.setTextViewText(R.id.worldcup, "還剩下" + days + "天");            appWidgetManager.updateAppWidget(widget, remoteViews);        }        public LYTimeTask(Context context, AppWidgetManager appWidgetManger) {            super();            this.appWidgetManager = appWidgetManger;            remoteViews = new RemoteViews(context.getPackageName(), R.layout.activity_main);            widget = new ComponentName(context, MainActivity.class);        }    };}

3、為Widget建立一個顯示用的布局檔案:main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  android:layout_width="match_parent"  android:layout_height="match_parent"  android:background="@drawable/worldcup"  android:orientation="vertical" >  <TextView    android:id="@+id/babybirthday"    android:layout_width="fill_parent"    android:layout_height="wrap_content"    android:text="@string/message"    android:textSize="12px"    android:textColor="#ff0000" /></LinearLayout>

4、修改程式自動產生的資訊清單檔。在AndroidManifest.xml中,聲明上述的AppWidgetProvider的子類是一個Receiver,並且:

(1)、該Receiver的intent-filter的Action必須包含“android.appwidget.action.APPWIDGET_UPDATE”;

(2)、該Receiver的meta-data為“android.appwidget.provider”,並用一個xml檔案來描述布局屬性。

<application  android:allowBackup="true"  android:icon="@drawable/ic_launcher"  android:label="@string/app_name"  android:theme="@style/AppTheme" >  <receiver    android:name=".MainActivity"    android:label="@string/app_name" >    <intent-filter>       <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /><!--廣播接收過濾器-->    </intent-filter>    <meta-data      android:name="android.appwidget.provider"      android:resource="@xml/AppWigdetProvider_Provider" /><!--AppWidgetProvider引用的Provider檔案-->  </receiver></application>

運行程式:進入WIDGETS頁面,可將Widget添加到HOME頁

在AppWidgetProvider類中,還有其它相關的方法

public class WidgetProvider extends AppWidgetProvider {    // 每接收一次廣播訊息就調用一次,使用頻繁    public void onReceive(Context context, Intent intent) {        super.onReceive(context, intent);    }    // 每次更新都調用一次該方法,使用頻繁    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {        super.onUpdate(context, appWidgetManager, appWidgetIds);    }     // 每刪除一個就調用一次    public void onDeleted(Context context, int[] appWidgetIds) {        super.onDeleted(context, appWidgetIds);    }     // 當該Widget第一次添加到案頭是調用該方法,可添加多次但只第一次調用    public void onEnabled(Context context) {        super.onEnabled(context);    }     // 當最後一個該Widget刪除是調用該方法,注意是最後一個    public void onDisabled(Context context) {        super.onDisabled(context);    }}

定義App Widgets布局檔案
定義AppWidgetProviderInfo資源
建立AppWidgetProvider類
建立App Widgets的配置Activity

App Widgets本質上是基於RemoteViews實現的,為了顯示App Widgets,需要首先建立布局檔案;

AppWidgetProviderInfo資源定義了App Widgets的中繼資料,如更新間隔、布局檔案、配置Activity。

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.