Android 8.1上狀態列新增截圖功能
1.需求
客戶要求在狀態列新增截圖功能。。
實現效果如下:
實現步驟
步驟1
在配置檔案alps\vendor\mediatek\proprietary\packages\apps\SystemUI\res\values\config.xml新增\screenshot 顯示
一個是固定位置顯示, 另一個是編輯時候的顯示
<string name="quick_settings_tiles_default" translatable="false"> wifi,bt,dnd,flashlight,rotation,battery,cell,airplane,cast,screenshot </string> <!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" --> <string name="quick_settings_tiles_stock" translatable="false"> wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location,hotspot,inversion,saver,work,cast,night,screenshot </string>
步驟2
在\vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\qs\tileimpl\QSFactoryImpl.java新增如下程式碼.
import com.android.systemui.qs.tiles.ScreenShotTile; public class QSFactoryImpl implements QSFactory { ...... public QSTile createTile(String tileSpec) { ...... else if (tileSpec.equals("screenshot")) return new ScreenShotTile(mHost); ...... } ...... }
步驟3
在alps\vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\qs\tiles目錄下新增一個類,ScreenShotTile.java
package com.android.systemui.qs.tiles; import com.android.systemui.R; import android.os.Message; import android.os.Handler; import android.content.Context; import android.content.Intent; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.screenshot.GlobalScreenshot; import android.os.RemoteException; import com.android.systemui.statusbar.policy.ScreenShotController; import android.os.Messenger; import com.android.systemui.qs.QSHost; import com.android.systemui.plugins.qs.QSTile.BooleanState; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.Dependency; public class ScreenShotTile extends QSTileImpl<BooleanState> { private static final String TAG = "ScreenShotTile"; private static final int SCREEN_SHOT_MESSAGE = 10000; private static GlobalScreenshot mScreenshot; private final ScreenShotController mScreenShotController; private final ActivityStarter mActivityStarter; Handler mHandler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case SCREEN_SHOT_MESSAGE: final Messenger callback = msg.replyTo; if (mScreenshot == null) { mScreenshot = new GlobalScreenshot(mContext); } mScreenshot.takeScreenshot(new Runnable() { @Override public void run() { Message reply = Message.obtain(null, 1); try { if(callback != null){ callback.send(reply); } }catch(RemoteException e){ } } }, msg.arg1 > 0, msg.arg2 > 0); break; default: break; } } }; public ScreenShotTile(QSHost host) { super(host); mScreenShotController=Dependency.get(ScreenShotController.class); mActivityStarter = Dependency.get(ActivityStarter.class); } @Override public BooleanState newTileState() { return new BooleanState(); } @Override public void handleSetListening(boolean listening) { } @Override protected void handleClick() { //mActivityStarter.postStartActivityDismissingKeyguard( // new Intent(), 0);//此方法會自動解鎖 mHost.collapsePanelsForce(); Message msg = mHandler.obtainMessage(SCREEN_SHOT_MESSAGE); mHandler.sendMessageDelayed(msg,1000); } @Override protected void handleLongClick() { //mActivityStarter.postStartActivityDismissingKeyguard( // new Intent(), 0);////此方法會自動解鎖 mHost.collapsePanelsForce(); Message msg = mHandler.obtainMessage(SCREEN_SHOT_MESSAGE); mHandler.sendMessageDelayed(msg,1000); } @Override public CharSequence getTileLabel() { return mContext.getString(R.string.screenshot); } @Override public Intent getLongClickIntent() { return new Intent(); } @Override protected void handleUpdateState(BooleanState state, Object arg) { state.value=false; //state.autoMirrorDrawable=false; state.label = mContext.getString(R.string.screenshot); state.icon = ResourceIcon.get(R.drawable.ic_qs_screenshot); //state.visible = true; } @Override public int getMetricsCategory(){ return MetricsEvent.QS_SCREEN_SHOT; } }
步驟4
新增一個介面alps\vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\statusbar\policy\ScreenShotController.java
package com.android.systemui.statusbar.policy;
public interface ScreenShotController{
boolean isSupportScreenShot();
}
步驟5
實現介面ScreenShotController.java
alps\vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\statusbar\policy\ScreenShotControllerImpl.java
package com.android.systemui.statusbar.policy;
import android.content.Context;
public class ScreenShotControllerImpl implements ScreenShotController{
private static final String TAG="ScreenShotControllerImpl";
private final Context mContext;
public ScreenShotControllerImpl(Context context)
{ mContext=context;
}
@Override
public boolean isSupportScreenShot()
{
return true;
}
}
步驟6
在alps\vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\Dependency.java定義
import com.android.systemui.statusbar.policy.ScreenShotController;
import com.android.systemui.statusbar.policy.ScreenShotControllerImpl;
......
public class Dependency extends SystemUI {
......
@Override
public void start() {
......
mProviders.put(ScreenShotController.class, () ->
new ScreenShotControllerImpl(mContext));
......
}
......
}
步驟7
alps\vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\screenshot\GlobalScreenshot.java修改許可權
class GlobalScreenshot 修改為 public
把
void takeScreenshot(Runnable finisher, boolean statusBarVisible, boolean navBarVisible) {
mDisplay.getRealMetrics(mDisplayMetrics);
takeScreenshot(finisher, statusBarVisible, navBarVisible, 0, 0, mDisplayMetrics.widthPixels,
mDisplayMetrics.heightPixels);
}
改成
public void takeScreenshot(Runnable finisher, boolean statusBarVisible, boolean navBarVisible) {
mDisplay.getRealMetrics(mDisplayMetrics);
takeScreenshot(finisher, statusBarVisible, navBarVisible, 0, 0, mDisplayMetrics.widthPixels,
mDisplayMetrics.heightPixels);
}
步驟8
至此 就可以實現截圖功能了 ,都是有個問題 就是在步驟3說的 ,mActivityStarter.postStartActivityDismissingKeyguard(
new Intent(), 0);呼叫此方法會自動解鎖 ,導致在鎖屏介面無法擷取鎖屏介面。
為此 新定義一個方法。
實現步驟3的collapsePanelsForce方法
在alps\vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\qs\QSHost.java新增
public interface QSHost {
......
void collapsePanelsForce();
......
}
步驟9
在alps\vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\qs\QSTileHost.java裡實現介面
/** Platform implementation of the quick settings tile host **/
public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory> {
......
/**
note screen
*/
@Override
public void collapsePanelsForce() {
mStatusBar.postAnimateCollapsePanelsForce();
}
......
}
步驟10
在alps\vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\statusbar\phone\StatusBar.java 新增如下方法
/**
* A:@ for screenshot
* */
public void animateCollapsePanelsForce() {
animateCollapsePanelsForce(CommandQueue.FLAG_EXCLUDE_NONE);
}
/**
* A:@ for screenshot
* */
private final Runnable mAnimateCollapsePanelsForce = new Runnable() {
@Override
public void run() {
animateCollapsePanelsForce();
}
};
/**
* A:@ for screenshot
* */
public void postAnimateCollapsePanelsForce() {
mHandler.post(mAnimateCollapsePanelsForce);
}
/**
* A:@ for screenshot
* */
public void animateCollapsePanelsForce(int flags) {
animateCollapsePanelsForce(flags, true /* force */, false /* delayed */,
1.0f /* speedUpFactor */);
}
/**
* A:@for screenshot
* */
public void animateCollapsePanelsForce(int flags, boolean force, boolean delayed,
float speedUpFactor) {
if (!force && mState != StatusBarState.SHADE) {
runPostCollapseRunnables();
return;
}
if (SPEW) {
Log.d(TAG, "animateCollapse():"
+ " mExpandedVisible=" + mExpandedVisible
+ " flags=" + flags);
}
if ((flags & CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL) == 0) {
if (!mHandler.hasMessages(MSG_HIDE_RECENT_APPS)) {
mHandler.removeMessages(MSG_HIDE_RECENT_APPS);
mHandler.sendEmptyMessage(MSG_HIDE_RECENT_APPS);
}
}
if (mStatusBarWindow != null) {
// release focus immediately to kick off focus change transition
mStatusBarWindowManager.setStatusBarFocusable(false);
mStatusBarWindow.cancelExpandHelper();
System.out.println("tuliyuan mstats is "+mState);
if(mState == StatusBarState.KEYGUARD) {
mStatusBarView.collapsePanelForce(true /* animate */, delayed, speedUpFactor);
}else{
mStatusBarView.collapsePanel(true /* animate */, delayed, 2.5f);//speedUpFactor ->2.5f
}
}
}
步驟11
在alps\vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\statusbar\phone\PanelBar.java新增如下方法
/**
* A:@ for screenshot
* */
public void collapsePanelForce(boolean animate, boolean delayed, float speedUpFactor) {
boolean waiting = false;
PanelView pv = mPanel;
if (animate && !pv.isFullyCollapsed()) {
//pv.collapse(true /* delayed */);
if(pv instanceof NotificationPanelView){
((NotificationPanelView)pv).animateCloseQs();
}else{
pv.collapse(true,speedUpFactor/* delayed */);
}
waiting = true;
} else {
pv.resetViews();
pv.setExpandedFraction(0); // just in case
pv.cancelPeek();
}
if (DEBUG) LOG("collapsePanel: animate=%s waiting=%s", animate, waiting);
if (!waiting && mState != STATE_CLOSED) {
// it's possible that nothing animated, so we replicate the termination
// conditions of panelExpansionChanged here
go(STATE_CLOSED);
onPanelCollapsed();
}
}
步驟12
在alps\frameworks\base\proto\src\metrics_constants.proto 新增定義
QS_SCREEN_SHOT = 1144;
步驟13
在資原始檔新增定義
<string name="screenshot">ScreenShot</string>
<string name="screenshot">截圖</string>
步驟14
新增圖片;也可以用向量畫出圖片
ic_qs_screenshot
到此已經實現啦。。。。。。