• Android Launcher 详解


    (1)      Launcher的定义:Android系统启动后,加载的第一个程序,是其他应用程序的入口。

    (2)      Launcher的构成:HomeScreen(1.workspace(AppWidget,Wallpaper,Livefolder,ShortCut),2.HotSeats,3.AllApps/allApplist:GridView)


    (3)      针对Launcher的开发类型:

        1.      开发自定义的Launcher

    2.      与Workspace相关的开发(AppWidget,Wallpaper,Livefolder,ShortCut)

    (4)      解读Launcher源代码(以ShortCut为例),Launcher为系统级应用,位于Applications层。源代码位于MyAndroidpackagesappsLauncher2中,可讲它导入eclipse中。

    (5)      看Manifest文件可知,Launcher的主Activity为:com.android.launcher2.Launcher。下面是它的部分配置信息:

    <activity
    android:name="com.android.launcher2.Launcher"
    android:launchMode="singleTask">
    <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>
    

    (6)      关于Activity的四种加载模式(android:launchMode):在多Activity开发中,有可能是自己应用之间的Activity跳转,或者夹带其他应用的可复用Activity。有可能会希望跳转到原来某个Activity实例,而不是产生大量重复的Activity。这就需要为Activity配置特定的加载模式,而不是默认的加载模式。

    1.      Standard:默认模式,每次激活Activity时都会创建Activity,并放入任务栈中。

    2.      singleTop:如果在任务栈栈顶正好存在该Activity的实例,就重用该实例(会调用实例的onNewIntent()),否则就会创建新的实例并放入栈顶,即使栈中已经存在该Activity的实例。

    3.      singleTask:如果在栈中已经有该Activity的实例,就会重用该实例,重用时,会让该实例回到栈顶,因此在它上面的实例将会被移出栈。

    4.      singleInstance:在一个新栈中创建该Activity的实例,并让多个应用共享该栈中的该Activity实例。一旦该模式的Activity实例已经存在于某个栈中,任何应用再激活该Activity时都会重用该栈中的实例( 会调用实例的onNewIntent() )。其效果相当于多个应用共享一个应用,不管谁激活该 Activity 都会进入同一个应用中。


    (7)      当用户按菜单键中的添加按钮或者长按workspace中的空白区域,会弹出一个对话框(如下图所示):





    @Override
    publicbooleanonOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    caseMENU_ADD:
    addItems(); /* 按菜单键,添加按钮*/
    returntrue;
    caseMENU_MANAGE_APPS:
    manageApps();
    returntrue;
    caseMENU_WALLPAPER_SETTINGS:
    startWallpaper();
    returntrue;
    caseMENU_SEARCH:
    
    @Override
    publicbooleanonOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    caseMENU_ADD:
    addItems(); /* 按菜单键,添加按钮*/
    returntrue;
    caseMENU_MANAGE_APPS:
    manageApps();
    returntrue;
    caseMENU_WALLPAPER_SETTINGS:
    startWallpaper();
    returntrue;
    caseMENU_SEARCH:
    onSearchRequested();
    returntrue;
    caseMENU_NOTIFICATIONS:
    showNotifications();
    returntrue;
            }
    
    returnsuper.onOptionsItemSelected(item);
        }
    
    privatevoidaddItems() {
    closeAllApps(true);
    showAddDialog(mMenuAddInfo); /* 显示对话框 */
    }
    
    // 长按workspace空白区域
    if (mWorkspace.allowLongPress()) {
    if (cellInfo.cell == null) {
    if (cellInfo.valid) {
    // User long pressed on empty space
    mWorkspace.setAllowLongPress(false);
    mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
    HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
    showAddDialog(cellInfo);/* 显示对话框 */
                    }
                } else {
    if (!(cellInfo.cellinstanceof Folder)) {
    // User long pressed on an item
    mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
    HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
    mWorkspace.startDrag(cellInfo);
                    }
                }
            }
    // showAddDialog方法
    privatevoidshowAddDialog(CellLayout.CellInfocellInfo) {
    mAddItemCellInfo = cellInfo;
    mWaitingForResult = true;
    showDialog(DIALOG_CREATE_SHORTCUT);
        }
    
    // showDialog方法会调用下面这个方法创建对话框
    protected Dialog onCreateDialog(int id) {
    switch (id) {
    caseDIALOG_CREATE_SHORTCUT: // 注意这里的常量
    returnnewCreateShortcut().createDialog();
    caseDIALOG_RENAME_FOLDER:
    returnnewRenameFolder().createDialog();
            }
    
    returnsuper.onCreateDialog(id);
        }
    
    // CreateShortcut为Launcher的内部类,看其中的pickShortcut()
    // 方法,它实现很多接口
    
    /**
         * Displays the shortcut creation dialog and launches, if necessary, theappropriate activity.
         */
    privateclassCreateShortcutimplementsDialogInterface.OnClickListener,
    DialogInterface.OnCancelListener, DialogInterface.OnDismissListener,
    DialogInterface.OnShowListener {
    
    privateAddAdaptermAdapter;
    
            Dialog createDialog() {
    mAdapter = newAddAdapter(Launcher.this);
    
    finalAlertDialog.Builder builder = newAlertDialog.Builder(Launcher.this);
    builder.setTitle(getString(R.string.menu_item_add_item));
    builder.setAdapter(mAdapter, this);
    
    builder.setInverseBackgroundForced(true);
    
    AlertDialog dialog = builder.create();
    dialog.setOnCancelListener(this);
    dialog.setOnDismissListener(this);
    dialog.setOnShowListener(this);
    
    return dialog;
            }
    
    publicvoidonCancel(DialogInterface dialog) {
    mWaitingForResult = false;
                cleanup();
            }
    
    publicvoidonDismiss(DialogInterface dialog) {
            }
    
    privatevoid cleanup() {
    try {
    dismissDialog(DIALOG_CREATE_SHORTCUT);
                } catch (Exception e) {
    // An exception is thrown if the dialog is not visible, which is fine
                }
            }
    
    /**
             * Handle the action clicked in the “Add to home” dialog.
             */
    publicvoidonClick(DialogInterface dialog, int which) {
                Resources res = getResources();
                cleanup();
    
    switch (which) {
    caseAddAdapter.ITEM_SHORTCUT: {
    // Insert extra item to handle picking application
    pickShortcut(); //当点击对话框中的快捷方式项,会//调用此方法
    break;
                    }
    
    caseAddAdapter.ITEM_APPWIDGET: {
    intappWidgetId = Launcher.this.mAppWidgetHost.allocateAppWidgetId();
    
                        Intent pickIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_PICK);
    pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
    // start the pick activity
    startActivityForResult(pickIntent, REQUEST_PICK_APPWIDGET);
    break;
                    }
    
    caseAddAdapter.ITEM_LIVE_FOLDER: {
    // Insert extra item to handle inserting folder
                        Bundle bundle = new Bundle();
    
    ArrayList<String>shortcutNames = newArrayList<String>();
    shortcutNames.add(res.getString(R.string.group_folder));
    bundle.putStringArrayList(Intent.EXTRA_SHORTCUT_NAME, shortcutNames);
    
    ArrayList<ShortcutIconResource>shortcutIcons =
    newArrayList<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);
    break;
                    }
    
    caseAddAdapter.ITEM_WALLPAPER: {
    startWallpaper();
    break;
                    }
                }
            }
    
    publicvoidonShow(DialogInterface dialog) {
    mWaitingForResult = true;            
            }
        }
    
    
    // pickShortcut()方法
    privatevoidpickShortcut() {
            Bundle bundle = new Bundle();
    
    ArrayList<String>shortcutNames = newArrayList<String>();
    shortcutNames.add(getString(R.string.group_applications));
    bundle.putStringArrayList(Intent.EXTRA_SHORTCUT_NAME, shortcutNames);
    
    ArrayList<ShortcutIconResource>shortcutIcons = newArrayList<ShortcutIconResource>();
            shortcutIcons.add(ShortcutIconResource.fromContext(Launcher.this,
    R.drawable.ic_launcher_application));
            bundle.putParcelableArrayList(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, shortcutIcons);
    
            Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY);
    pickIntent.putExtra(Intent.EXTRA_INTENT, new Intent(Intent.ACTION_CREATE_SHORTCUT));
    pickIntent.putExtra(Intent.EXTRA_TITLE, getText(R.string.title_select_shortcut));
    pickIntent.putExtras(bundle);
    
    startActivityForResult(pickIntent,REQUEST_PICK_SHORTCUT); // 启动了一个Activity,其实是一个快捷方式//列表,一个回调方法
        }
    
    
    // 在onActivityResult()中
    
    caseREQUEST_PICK_SHORTCUT:
    processShortcut(data); // 回调此方法,data为Intent
    break;
    
    voidprocessShortcut(Intent intent) {
    // Handle case where user selected "Applications"
            String applicationName = getResources().getString(R.string.group_applications);
            String shortcutName = intent.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
    
    if (applicationName != null&&applicationName.equals(shortcutName)) {
                Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
    mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
    
                Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY);
    pickIntent.putExtra(Intent.EXTRA_INTENT, mainIntent);
    pickIntent.putExtra(Intent.EXTRA_TITLE, getText(R.string.title_select_application));
    startActivityForResultSafely(pickIntent, REQUEST_PICK_APPLICATION);
            } else {
    startActivityForResultSafely(intent, REQUEST_CREATE_SHORTCUT); //这里还要启动一个Activity
            }
        }
    
    
    caseREQUEST_CREATE_SHORTCUT:
    completeAddShortcut(data, mAddItemCellInfo);
    break;
    
    
    /**
         * Add a shortcut to the workspace.
         *
         * @param data The intent describing the shortcut.
         * @paramcellInfo The position on screen where to create the shortcut.
         */
    privatevoidcompleteAddShortcut(Intent data, CellLayout.CellInfocellInfo) {
    cellInfo.screen = mWorkspace.getCurrentScreen();
    if (!findSingleSlot(cellInfo)) return;
    
    finalShortcutInfo info = mModel.addShortcut(this, data, cellInfo, false);
    
    if (!mRestoring) {
    final View view = createShortcut(info);
    mWorkspace.addInCurrentScreen(view, cellInfo.cellX, cellInfo.cellY, 1, 1,
    isWorkspaceLocked());
            }
        }
    

    (8)      如何让你的应用支持创建Shortcut,即你的应用能够出现在快捷方式列表中。

    //  单独创建一个Activity,例如ShortCut.java
    //  配置此Activity
    <activity 
    android:name=".ShortCut">
    <intent-filter>
    <actionandroid:name="android.intent.action.CREATE_SHORTCUT"/>
    </intent-filter>
    </activity>
    // 以下是它的代码,这个startActivityForResultSafely(intent, //REQUEST_CREATE_SHORTCUT)方法会跳到这个Activity
    publicclassShortCutextends Activity {
    
    	@Override
    	protectedvoidonCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		if(getIntent().getAction().equals(Intent.ACTION_CREATE_SHORTCUT)) {
    			Intent returnIntent = new Intent();
    			returnIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "应用管理器");
    			returnIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, new Intent(this, ShowAppActivity.class));
    			/* returnIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, 
    			Intent.ShortcutIconResource.fromContext(this, R.drawable.icon)); */
    			returnIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON, R.drawable.icon);
    			setResult(RESULT_OK, returnIntent);
    			finish();
    		}
    	}
    
    }
    
    

    (9)      如何在用户第一次启动应用后,提示用户是否要创建Shortcut:现在Manifest文件中添加一个权限(<permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"></permission>)只要向Launcher发送一个广播,数据为一个Intent。此Intent与上面代码中的returnIntent类似,只要这个Intent添加一个Action(

    intent.setAction("com.android.launcher.action.INSTALL_SHORTCUT"))。然后sendBroadcast(intent)。在Launcher中有个InstallShortcutReceiver.java,接受这个广播。





  • 相关阅读:
    android 去掉屏幕上的title bar(转载)
    关于手机中的点点滴滴
    oracle 导入数据
    Neither the JAVA_HOME nor the JRE_HOME environment variable is defined 20130307 21:35 3946人阅读 评论(0) 收藏
    图片文字绝对居中,并排显示
    Neither the JAVA_HOME nor the JRE_HOME environment variable is defined
    给第三方dll强签名
    Socket套接字
    推荐一个IE6下js调试工具(Companion.JS)
    jquery form 插件 分类: JavaScript 20130121 13:59 1779人阅读 评论(0) 收藏
  • 原文地址:https://www.cnblogs.com/bill-technology/p/4130845.html
Copyright © 2020-2023  润新知