In Drag Analysis (Part I) In this paper, we analyze the onLong Click method in Launcher.java, in which WorkSpace judges the location of TouchDown event by onInterceptTouchEvent method, and uses setTag method to save the cell Info where the click is located. If the cell variable in Infcello is not empty, it indicates that the current long click is a shortcut icon and needs to enter startDrag. Line dragging; if the cell variable is empty, it means that there is no control in the long press, and it goes into the logic of wallpaper selection. At that time, we did not go deep into it. Today's article complements Launcher's wallpaper selection process.
As you can see from onLongClick, Launcher.java's startWallpaper method is invoked after giving long press vibration feedback:
/** * Jump Wallpaper Selection Page */ private void startWallpaper() { showWorkspace(true); final Intent pickWallpaper = new Intent(Intent.ACTION_SET_WALLPAPER); /** * Provide a list of Activities that match intent for user selection */ Intent chooser = Intent.createChooser(pickWallpaper, getText(R.string.chooser_wallpaper)); startActivityForResult(chooser, REQUEST_PICK_WALLPAPER); }
In startWallpager, first animation shows Workspace (currently on the desktop, so this method does not execute the animation code segment internally), then implicit intent is used to start the application conforming to Intent.ACTION_SET_WALLPAGER. If there are more than one eligible application, the system will pop up the pop-up box for the user to choose the application to open. The specific pop-up box is shown in the following figure:
From this picture, we can see that the applications that satisfy the conditions of Intent.ACITON_SET_WALLPAGER include Launcher 3, Launcher (this application), Live Wallpagers, Photos and Pictures. Here we study our own application Luancher. We can see that the wallpaper selection page in Android Manifest.xml file is Wallpager Chooser:
<activity android:name="com.android.launcher2.WallpaperChooser" android:theme="@style/Theme.WallpaperPicker" android:label="@string/pick_wallpaper" android:icon="@mipmap/ic_launcher_wallpaper" android:finishOnCloseSystemDialogs="true" android:process=":wallpaper_chooser"> <intent-filter> <action android:name="android.intent.action.SET_WALLPAPER" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> <meta-data android:name="android.wallpaper.preview" android:resource="@xml/wallpaper_picker_preview" /> </activity>
It should be noted that this Intent needs to use permissions:
<uses-permission android:name="android.permission.SET_WALLPAPER" /> <uses-permission android:name="android.permission.SET_WALLPAPER_HINTS" />
In Wallpager Chooser, you start a Fragment for wallpaper selection, in Wallpager Chooser Dialog Fragment's onCreate:
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { findWallpapers(); /* If this fragment is embedded in the layout of this activity, then we should * generate a view to display. Otherwise, a dialog will be created in * onCreateDialog() */ if (mEmbedded) { View view = inflater.inflate(R.layout.wallpaper_chooser, container, false); view.setBackground(mWallpaperDrawable); final Gallery gallery = (Gallery) view.findViewById(R.id.gallery); gallery.setCallbackDuringFling(false); gallery.setOnItemSelectedListener(this); gallery.setAdapter(new ImageAdapter(getActivity())); View setButton = view.findViewById(R.id.set); setButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { selectWallpaper(gallery.getSelectedItemPosition()); } }); return view; } return null; } private void selectWallpaper(int position) { try { WallpaperManager wpm = (WallpaperManager) getActivity().getSystemService( Context.WALLPAPER_SERVICE); wpm.setResource(mImages.get(position)); Activity activity = getActivity(); activity.setResult(Activity.RESULT_OK); activity.finish(); } catch (IOException e) { Log.e(TAG, "Failed to set wallpaper: " + e); } }
First, the default wallpaper is loaded into the mThumbs (thumbnails) and mImages (original images) collection.
2. Then use a layout filled with Gallery and wallpaper confirmation buttons to display wallpaper thumbnails in the collection in Gallery.
3. In the confirmation button click event, select the icon selected in Gallery and set the currently selected bitmap to Wallpager Manager.
To add some knowledge, Android system has a wallpaper window under the Activity window, which is located at the bottom. Our bitmap is set to the Wallpager Manager, which calls the setWallpager method of the Wallpager Manager Service to save the bitmap in a defined file. FileObserver is then used to notify the Engine of WallpagerService (actually its subclass, ImageWallpager) to draw mBackground in the wallpaper window (obtained by the getBitmap method of WallpagerManager).
Since the Activity window is above the wallpaper window, we need to make the Activity window semi-transparent or fully transparent to display the wallpaper window. In fact, Launcher.java does exactly that when we display the Workspace, that is, when on Resume and changing the wallpaper visibility FLAG, Launcher.xml's Root View background is R.drawable.workspace_bg's transparent background. Here is the code in Launcher.java that changes wallpaper visibility. It will be called when all apps pages appear or disappear, when all apps pages disappear, visible=true, and vice versa.
void updateWallpaperVisibility(boolean visible) { int wpflags = visible ? WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER : 0; int curflags = getWindow().getAttributes().flags & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; if (wpflags != curflags) { getWindow().setFlags(wpflags, WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER); } setWorkspaceBackground(visible); }
You can see that you can display wallpaper by setting FLAG_SHOW_WALLPAGER attribute to Window s. In fact, we have achieved the same goal by setting themes to Launcher.java in our list file, which is why we can display wallpaper windows at the bottom of Lancher's workspace for the first time.
<style name="Theme.Holo.Wallpaper"> <item name="windowBackground">@color/transparent</item> <item name="colorBackgroundCacheHint">@null</item> <item name="windowShowWallpaper">true</item> </style>
By setting a transparent color to the Activity window and adding the Windows Show Wallpager attribute to true, you can ensure that the wallpaper window can be displayed using Activeness inherited from this topic.
This summary:
If the application needs to set the function of wallpaper, it needs to add the action of IntentFilter to the wallpaper page as android.intent.action.SET_WALLPAPER and declare the permission of SET_WALLPAGER. When users complete wallpaper selection, they need to set wallpaper to wallpaper window through one of the methods of setBitmap, setResource and setStream of WallPager Manager.
2. If an Activity page of the current application wants to display a wallpaper window under its window, you can let the Activity window use the wallpaper theme that comes with the system, or add the windows backgroundand windows show wallpager attributes using the theme of the Activity window of other topics, of course! You can also add FLAG_SHOW_WALLPAGER in the code by window.setFlag to achieve the same effect.