Practical development of the detailed source code of the android vehicle widget widget - Practical course on the development of the Qianli Ma vehicle framework

Official website reference link: https://developer.android.google.cn/develop/ui/views/appwidgets/overview

1. What is a widget?

App widgets are miniature application views that can be embedded in other applications (such as the home screen) and receive periodic updates.
Popular explanation: A miniature view that can be refreshed periodically and added to other applications.
For more android framework content, please chat with Qianlima privately: https://www.bilibili.com/video/BV1wj411o7A9/

2. What is the operating mechanism of widgets?

Insert image description hereDefine the behavior of the widget through AppWidgetProvider
Define the UI of the widget through RemoteView and layout files
Update the view through AppWidgetManager
Register AppWidgetProvider (inherited from broadcast) in the manifest and set the listening action

3. What process does the widget run in?

First, let’s understand the Host process and widget process, as shown in the figure below:
Insert image description here
the processes involved in widget operation, and the responsibilities of each process:
Insert image description here

The running logic of the widget needs to be divided into three parts: the logic in the AppWidgetProvider runs in the application process where the widget is located. The data storage of widgets, the logic of permission verification, and the communication bridge between the widget process and the host process, that is, the cross-process communication intermediary, run in system_process. The widget rendering logic is in the host process.

4. How does RemoteView work?

RemoteView inherits from Parcelable and can be passed between processes. RemoteView will convert each set behavior into a corresponding Action. Action is then translated into the corresponding behavior during the Host side process.

For example: the setText method of
the normal own process
TextView, just call mTextView.setText directly
, but this widget is not rendered by its own widget process, here it can only be operated through RemoteView, the principle of RemoteView is actually, the transfer class is a method name character, because the string can be passed across processes, and then reaches the Host process, the Host process can make reflection calls based on the string of the method name. The
schematic diagram is as follows:
Insert image description here

It can be seen that the essence of RemoteViews is a medium that can control and display views across processes. It is not as convenient as controlling your own view. The control interfaces corresponding to views need to be converted one by one, so it is still very inflexible, and pay attention here, because view There may be many types, but remoteviews only have fixed ones and do not support arbitrary views or customization.
Insert image description here

5. Widget development part

AppWidgetProviderInfo object 
Describes the metadata for an App Widget, such as the App Widget's layout, update frequency, and the AppWidgetProvider class. This should be defined in XML.
AppWidgetProvider class implementation
Defines the basic methods that allow you to programmatically interface with the App Widget, based on broadcast events. Through it, you will receive broadcasts when the App Widget is updated, enabled, disabled and deleted.

1 Prepare the AppWidgetProviderInfo information
AppWidgetProviderInfo mainly describes the metadata of the Widget, such as the layout of the widget and the update frequency, which are generally defined in xml

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="60dp"
    android:minHeight="30dp"
    android:updatePeriodMillis="86400000"
    android:initialLayout="@layout/appwidget_provider"
    android:configure="com.example.android.apis.appwidget.ExampleAppWidgetConfigure"
    android:resizeMode="horizontal"
    >
</appwidget-provider>

The most important thing is that initialLayout will have an initial layout, that is, the default display layout of the widget, that is, the default layout displayed before the widget program has not called updateWidget of the code

layout/appwidget_provider

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/appwidget_text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="#ffff00ff"
    android:textColor="#ff000000"
/>

2 Prepare the AppWidgetProvider implementation class.
The implementation class of AppWidgetProvider
is based on broadcasting, and the callback notifies the AppWidget situation, such as update, enable, disabled and other notifications

public class ExampleAppWidgetProvider extends AppWidgetProvider {
    
    

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
    
    
        //省略
    }
    //省略
}

3 Register in manifest

     <receiver android:name=".appwidget.ExampleAppWidgetProvider">
            <meta-data android:name="android.appwidget.provider"
                    android:resource="@xml/appwidget_provider" />
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>
        </receiver>

The meta-data tag is also very important, it is the xml linked to AppWidgetProviderInfo

4. How to update widget’s UI through code

  static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
            int appWidgetId, String titlePrefix) {
    
    

        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider);
        views.setTextViewText(R.id.appwidget_text, text);

        // Tell the widget manager
        appWidgetManager.updateAppWidget(appWidgetId, views);
    }

Mainly build the corresponding RemoteViews through the layout, then perform related set operations on the specific View in the layout, and finally call the updateAppWidget method of appWidgetManager to update the AppWidget

For the relevant demo address, you need to download the aosp source code:
aosp/development/samples/ApiDemos/src/com/example/android/apis/appwidget/

The widget is displayed on the widget page of the mobile phone desktop. Because the manifest configuration of the previous widget is configured, the desktop can be scanned and displayed: After
Insert image description here
dragging to the desktop successfully, the widget displays as follows:
Insert image description here

6. Detailed explanation of Widget’s display Host process

In aosp's CarLauncher, the function code itself is very simple, and there is no need for the display of the relevant appwidget, but the mobile desktop has a complete code part as the widgethost. So understanding how to clear a WidgetHost becomes very important.

need

App widget host: The AppWidgetHost provides the interaction with the AppWidget service for apps that want to embed app widgets in their UI. An AppWidgetHost must have an ID that is unique within the host's own package. This ID remains persistent across all uses of the host. The ID is typically a hard-coded value that you assign in your application.

App widget ID: Each widget instance is assigned a unique ID at the time of binding (see bindAppWidgetIdIfAllowed(), covered in more detail in Binding widgets on this page. The unique ID is obtained by the host using allocateAppWidgetId(). This ID is persistent across the lifetime of the widget, that is, until it is deleted from the host. Any host-specific state (such as the size and location of the widget) should be persisted by the hosting package and associated with the app widget ID.

App widget host view: Think of AppWidgetHostView as a frame that the widget is wrapped in whenever it needs to be displayed. A widget is associated with an AppWidgetHostView every time the widget is inflated by the host. Note the following points:

By default, the system will create an AppWidgetHostView, but the host can create its own subclass of AppWidgetHostView by extending it.
Starting in Android 12 (API level 31), AppWidgetHostView introduces the the setColorResources() and resetColorResources() methods for handling dynamically overloaded colors. The host is responsible for providing the colors to these methods.

AppWidgetHost is responsible for interacting with the AppWidget service of the system system server. Each AppWidgetHost needs to have an independent id, which means that not only the desktop can be used as a host, but the most common one is the desktop, which also means that there can be multiple hosts. Also show widgets
Insert image description here

App widget ID means that each App Widget instance will have an independent id, which is obtained through the allocateAppWidgetId method of AppWidgetHost, mainly because this id is required when the widget is bound, that is, the bindAppWidgetIdIfAllowed method requires this id.

AppWidgetHostView
serves as the view that renders the widget and is responsible for inflating the related views of the widget.

The required permissions
BIND_APPWIDGET permission levels are as follows:
Insert image description hereplatform signatures are required, or built-in priv/apps are required. In fact, CarLauncher is generally satisfied, and the platform signatures are generally the same as the system.

Specific actual analysis (refer to aosp’s source code demo: development/apps/WidgetPreview/src/com/android/widgetpreview/WidgetPreviewActivity.java):

  第一步,根据独特HOST_ID,构造出AppWidgetHost :
  mAppWidgetHost = new AppWidgetHost(getApplicationContext(), APPWIDGET_HOST_ID);
  第二步,AppWidgetHost 申请出独特的widget id:
  int id = mAppWidgetHost.allocateAppWidgetId();
  第三步,用申请的widget id绑定到对应的widget的provider的componentName:
  mAppWidgetManager.bindAppWidgetId(mAppWidgetId, intent.getComponent(), options);
  第四步,获取providerInfo,创建对应的AppWidgetHostView,进行add:
	 AppWidgetProviderInfo providerInfo =
            AppWidgetManager.getInstance(getBaseContext()).getAppWidgetInfo(appWidgetId);
mAppWidgetView = mAppWidgetHost.createView(getBaseContext(), appWidgetId, providerInfo);
mAppWidgetFrame.addView(mAppWidgetView, mPreviewWidth, mPreviewHeight);

Insert image description herePhenomenon demonstration:
Insert image description here

Guess you like

Origin blog.csdn.net/learnframework/article/details/132707953