做设计必须知道的几个网站,wordpress 搜索筛选器,用老薛主机做网站,wordpress nginx apache摘要#xff1a;android原生有双屏的机制#xff0c;但需要芯片厂商适配框架后在底层实现。本文在基于芯发8766已实现底层适配的基础上#xff0c;仅针对上层Launcher部分对系统进行改造#xff0c;从而实现在开机后副屏显示一张待机图片。 
副屏布局 
由于仅显示一张图片android原生有双屏的机制但需要芯片厂商适配框架后在底层实现。本文在基于芯发8766已实现底层适配的基础上仅针对上层Launcher部分对系统进行改造从而实现在开机后副屏显示一张待机图片。 
副屏布局 
由于仅显示一张图片故布局仅需填充ImageView 
Index: vendor/mediatek/proprietary/packages/apps/Launcher3/res/layout/presentation_image.xml--- vendor/mediatek/proprietary/packages/apps/Launcher3/res/layout/presentation_image.xml	(不存在的)vendor/mediatek/proprietary/packages/apps/Launcher3/res/layout/presentation_image.xml	(版本 1687)-0,0 1,6 
ImageViewxmlns:androidhttp://schemas.android.com/apk/res/androidandroid:idid/image_viewandroid:layout_widthmatch_parentandroid:layout_heightmatch_parentandroid:scaleTypecenterInside /关于android:scaleType的详细说明和用法可参考官网API 或者以下BLOG Android的ImageView scaleType八大属性你都了解吗 android学习笔记之ImageView的scaleType属性 
准备一张符合副屏分辨率的图片 
博主所使用的副屏为320x240图片格式为JPG 
Index: vendor/mediatek/proprietary/packages/apps/Launcher3/res/mipmap-hdpi/presents.jpg副屏图片管理类 
新增图换图片功能在显示以上图片的基础上如果所指定路径有替换的图片文件则使用替换的图片文件。 
Index: vendor/mediatek/proprietary/packages/apps/Launcher3/src/com/android/launcher3/presentation/ImagePresentation.java--- vendor/mediatek/proprietary/packages/apps/Launcher3/src/com/android/launcher3/presentation/ImagePresentation.java	(不存在的)vendor/mediatek/proprietary/packages/apps/Launcher3/src/com/android/launcher3/presentation/ImagePresentation.java	(版本 1687)-0,0 1,48 
package com.android.launcher3.presentation;import android.app.Presentation;
import android.content.Context;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Display;
import android.widget.ImageView;import com.android.launcher3.R;import java.io.File;public class ImagePresentation extends Presentation {private static final String TAG  ImagePresentation;ImageView imageView;public ImagePresentation(Context context, Display display) {super(context, display);}Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.presentation_image);imageView  findViewById(R.id.image_view);imageView.setImageResource(R.mipmap.presents);}Overrideprotected void onStart() {super.onStart();String path  Environment.getExternalStorageDirectory().getAbsolutePath()  /presents_replace.jpg;File imageFile  new File(path);if (imageFile.exists()) {imageView.setImageURI(Uri.fromFile(new File(path)));} else {Log.d(TAG, The replacement image does not exist, use the original image);}}
} 
在Launcher部分的实现 
由于需要开机后显示待机的图片并且副屏的内容默认是投射填充主屏的内容故开机后会有准备阶段主要显示一部分Launcher的内容在完全准备好后再显示副屏的待机图片。 
Index: vendor/mediatek/proprietary/packages/apps/Launcher3/src/com/android/launcher3/Launcher.java--- vendor/mediatek/proprietary/packages/apps/Launcher3/src/com/android/launcher3/Launcher.java	(版本 1678)vendor/mediatek/proprietary/packages/apps/Launcher3/src/com/android/launcher3/Launcher.java	(版本 1687)-70,6 70,7 import android.app.NotificationChannel;import android.app.NotificationManager;import android.app.PendingIntent;
import android.app.Presentation;import android.appwidget.AppWidgetHostView;import android.appwidget.AppWidgetManager;import android.content.ActivityNotFoundException;-86,6 87,7 import android.graphics.Bitmap;import android.graphics.Rect;import android.graphics.RectF;
import android.hardware.display.DisplayManager;import android.os.Build;import android.os.Bundle;import android.os.CancellationSignal;-99,6 101,7 import android.text.method.TextKeyListener;import android.util.Log;import android.util.SparseArray;
import android.view.Display;import android.view.KeyEvent;import android.view.KeyboardShortcutGroup;import android.view.KeyboardShortcutInfo;-168,6 171,7 import com.android.launcher3.popup.PopupContainerWithArrow;import com.android.launcher3.popup.PopupDataProvider;import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.presentation.ImagePresentation;import com.android.launcher3.qsb.QsbContainerView;import com.android.launcher3.statemanager.StateManager;import com.android.launcher3.statemanager.StateManager.StateHandler;-387,6 391,11 private StringCache mStringCache;    //   {private DisplayManager mDisplayManager;private Presentation secondaryPresentation;//   }
OverrideTargetApi(Build.VERSION_CODES.S)protected void onCreate(Bundle savedInstanceState) {-453,6 462,34 super.onCreate(savedInstanceState);        //   {mDisplayManager  (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);mDisplayManager.registerDisplayListener(new DisplayManager.DisplayListener() {Overridepublic void onDisplayAdded(int displayId) {Log.d(TAG, onDisplayAdded);}Overridepublic void onDisplayRemoved(int displayId) {Log.d(TAG, onDisplayRemoved);}Overridepublic void onDisplayChanged(int displayId) {}}, null);Display[] displays  mDisplayManager.getDisplays();for (Display display : displays) {if (display.getDisplayId() ! Display.DEFAULT_DISPLAY) {secondaryPresentation  new ImagePresentation(this, display);//secondaryPresentation  new VideoPresentation(this, display);secondaryPresentation.show();break;}}//   }
LauncherAppState app  LauncherAppState.getInstance(this);mOldConfig  new Configuration(getResources().getConfiguration());mModel  app.getModel();-1718,6 1755,12 mOverlayManager.onActivityDestroyed(this);mUserChangedCallbackCloseable.close();//   {if (secondaryPresentation ! null  secondaryPresentation.isShowing()) {secondaryPresentation.dismiss();}//   }}public LauncherAccessibilityDelegate getAccessibilityDelegate() { 
扩展 —— 副屏视频布局 
能显示图片自然也能播放视频 
Index: vendor/mediatek/proprietary/packages/apps/Launcher3/res/layout/presentation_video.xml--- vendor/mediatek/proprietary/packages/apps/Launcher3/res/layout/presentation_video.xml	(不存在的)vendor/mediatek/proprietary/packages/apps/Launcher3/res/layout/presentation_video.xml	(版本 1687)-0,0 1,7 
?xml version1.0 encodingutf-8?
VideoViewxmlns:androidhttp://schemas.android.com/apk/res/androidandroid:idid/video_viewandroid:layout_widthmatch_parentandroid:layout_heightmatch_parentandroid:scaleTypecenterCrop / 
准备一段符合副屏分辨率的视频 
博主所使用的副屏为320x240视频格式为MP4 
Index: vendor/mediatek/proprietary/packages/apps/Launcher3/res/raw/video_320_240.mp4副屏视频管理类 
播放的视频内容需要根据副屏的比例进行缩放并且根据实际情况实现循环播放。 
Index: vendor/mediatek/proprietary/packages/apps/Launcher3/src/com/android/launcher3/presentation/VideoPresentation.java--- vendor/mediatek/proprietary/packages/apps/Launcher3/src/com/android/launcher3/presentation/VideoPresentation.java	(不存在的)vendor/mediatek/proprietary/packages/apps/Launcher3/src/com/android/launcher3/presentation/VideoPresentation.java	(版本 1687)-0,0 1,68 
package com.android.launcher3.presentation;import android.app.Presentation;
import android.content.Context;
import android.graphics.Point;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.Display;
import android.view.ViewGroup;
import android.widget.VideoView;import com.android.launcher3.R;public class VideoPresentation extends Presentation {private static final String TAG  VideoPresentation;private VideoView videoView;public VideoPresentation(Context context, Display display) {super(context, display);}Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.presentation_video);videoView  findViewById(R.id.video_view);Uri videoUri  Uri.parse(android.resource://  getContext().getPackageName()  /  R.raw.video_320_240);videoView.setVideoURI(videoUri);videoView.setOnPreparedListener(mp - {int videoWidth  mp.getVideoWidth();int videoHeight  mp.getVideoHeight();Point screenSize  new Point();getDisplay().getRealSize(screenSize);int screenWidth  screenSize.x;int screenHeight  screenSize.y;float widthRatio  (float) screenWidth / videoWidth;float heightRatio  (float) screenHeight / videoHeight;float scale  Math.min(widthRatio, heightRatio);ViewGroup.LayoutParams params  videoView.getLayoutParams();params.width  (int) (videoWidth * scale);params.height  (int) (videoHeight * scale);videoView.setLayoutParams(params);});videoView.setOnCompletionListener(mp - {videoView.start(); // replay});videoView.start();}Overrideprotected void onStop() {super.onStop();if (videoView ! null) {videoView.stopPlayback();}}
}