安卓8.0 SystemUI 中的quick setting加入屏幕截图功能



   在安卓8.0的QS中增加一个选项 和在安卓7.0上的大致相同,可能还会有一点点的小区别。现在开始总结一下,如果有什么问题,欢迎提出。嘿嘿

     1.首先在/frameworks/base/packages/SystemUI/res/values/config.xml里面添加截屏screenshot的选项



        wifi,cell,battery,dnd,flashlight,screenshot
  

     2.当然了/frameworks/base/packages/SystemUI/res/values/strings.xml里面还要加一个字符串

Screenshot

     3.下面就开始重点了frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenShotTile.java
 要在这个tiles这个文件夹下面添加这个java文件,注意这里继承的是QSTileImpl,这点和7.0不一样。

package com.android.systemui.qs.tiles;

import android.content.res.Configuration;
import android.content.res.Resources;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.android.systemui.R;
//import com.android.systemui.qs.QSTile;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import android.content.Intent;
import android.util.Log;

import android.content.Context;
import com.android.internal.logging.MetricsLogger;
//import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;

import android.content.ServiceConnection;
import android.content.ComponentName;
import android.os.Message;
import android.os.Messenger;
import android.os.Handler;
import android.os.IBinder;
import android.os.UserHandle;
import android.os.RemoteException;
import android.os.ServiceManager;
import com.android.systemui.plugins.qs.QSTile.BooleanState;
import com.android.systemui.qs.QSHost;
import android.widget.Switch;

public class ScreenShotTile extends QSTileImpl {

    public ScreenShotTile(QSHost host) {
        super(host);
    }

    @Override
    public BooleanState newTileState() {
        return new BooleanState();
    }

    @Override
    protected void handleClick() {
        mHost.screenShot();
    }

    @Override
    public int getMetricsCategory() {
        return MetricsEvent.QS_PANEL;
    }

    @Override
    public Intent getLongClickIntent() {
        return new Intent(mContext,com.android.systemui.screenshot.ScreenShotActivity.class);
    }

    @Override
    public CharSequence getTileLabel() {
        return mContext.getString(R.string.quick_settings_screenshot);
    }

    @Override
    protected void handleUpdateState(BooleanState state, Object arg) {
        state.label = mContext.getString(R.string.quick_settings_screenshot);
        state.icon = state.icon = ResourceIcon.get(R.drawable.icon_screenshot);
        state.value = false;
        //return;
        state.expandedAccessibilityClassName = Switch.class.getName();
    }

    public void setListening(boolean listening) {
    }

    final Object mScreenshotLock = new Object();
    ServiceConnection mScreenshotConnection = null;
    private Handler mHandler = new Handler();

    final Runnable mScreenshotTimeout = new Runnable() {
        @Override public void run() {
            synchronized (mScreenshotLock) {
                if (mScreenshotConnection != null) {
                    mContext.unbindService(mScreenshotConnection);
                    mScreenshotConnection = null;
                }
            }
        }
    };

    private final Runnable mScreenshotRunnable = new Runnable() {
        @Override
        public void run() {
            takeScreenshot();
        }
    };

    private void takeScreenshot() {
        synchronized (mScreenshotLock) {
            if (mScreenshotConnection != null) {
                return;
            }
            ComponentName cn = new ComponentName("com.android.systemui",
                    "com.android.systemui.screenshot.TakeScreenshotService");
            Intent intent = new Intent();
            intent.setComponent(cn);
            ServiceConnection conn = new ServiceConnection() {
                @Override
                public void onServiceConnected(ComponentName name, IBinder service) {
                    synchronized (mScreenshotLock) {
                        if (mScreenshotConnection != this) {
                            return;
                        }
                        Messenger messenger = new Messenger(service);
                        Message msg = Message.obtain(null, 1);
                        final ServiceConnection myConn = this;
                        Handler h = new Handler(mHandler.getLooper()) {
                            @Override
                            public void handleMessage(Message msg) {
                                synchronized (mScreenshotLock) {
                                    if (mScreenshotConnection == myConn) {
                                        mContext.unbindService(mScreenshotConnection);
                                        mScreenshotConnection = null;
                                        mHandler.removeCallbacks(mScreenshotTimeout);
                                    }
                                }
                            }
                        };
                        msg.replyTo = new Messenger(h);
                        msg.arg1 = msg.arg2 = 0;
                        try {
                            messenger.send(msg);
                        } catch (RemoteException e) {
                        }
                    }
                }
                @Override
                public void onServiceDisconnected(ComponentName name) {}
            };
            if (mContext.bindServiceAsUser(
                    intent, conn, Context.BIND_AUTO_CREATE, UserHandle.CURRENT)) {
                mScreenshotConnection = conn;
                mHandler.postDelayed(mScreenshotTimeout, 15000);
            }
        }
    }
}


4.在/frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSHost.java 文件中加入方法screenshot方法。

import java.util.Collection;

public interface QSHost {
    void warn(String message, Throwable t);
    void collapsePanels();
    void forceCollapsePanels();
   ///M:START@{
        void screenShot();
   ///END @}
    void openPanels();
    Context getContext();
    Collection getTiles();
    void addCallback(Callback callback);
    void removeCallback(Callback callback);
    TileServices getTileServices();
    void removeTile(String tileSpec);

5.在/frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java中加入相应方法

 @Override
    public void warn(String message, Throwable t) {
        // already logged
    }
    ///START@{
    @Override
    public void screenShot() {
        mStatusBar.screenShot();
    }
    /// END @}
    @Override
    public void collapsePanels() {
        mStatusBar.postAnimateCollapsePanels();
    }

    @Override
    public void forceCollapsePanels() {
        mStatusBar.postAnimateForceCollapsePanels();
    }

6.在/frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java,这个里面会加载所有的title 这个也是8.0上新增加的。

需要导包import com.android.systemui.qs.tiles.ScreenShotTile;
public QSTile createTile(String tileSpec) {
        if (tileSpec.equals("wifi")) return new WifiTile(mHost);
        else if (tileSpec.equals("bt")) return new BluetoothTile(mHost);
        else if (tileSpec.equals("cell")) return new CellularTile(mHost);
        else if (tileSpec.equals("dnd")) return new DndTile(mHost);
        else if (tileSpec.equals("inversion")) return new ColorInversionTile(mHost);
        else if (tileSpec.equals("airplane")) return new AirplaneModeTile(mHost);
        else if (tileSpec.equals("work")) return new WorkModeTile(mHost);
        else if (tileSpec.equals("rotation")) return new RotationLockTile(mHost);
        else if (tileSpec.equals("flashlight")) return new FlashlightTile(mHost);
        else if (tileSpec.equals("location")) return new LocationTile(mHost);
        else if (tileSpec.equals("cast")) return new CastTile(mHost);
        else if (tileSpec.equals("hotspot")) return new HotspotTile(mHost);
        else if (tileSpec.equals("user")) return new UserTile(mHost);
        else if (tileSpec.equals("battery")) return new BatterySaverTile(mHost);
        else if (tileSpec.equals("saver")) return new DataSaverTile(mHost);
        else if (tileSpec.equals("night")) return new NightDisplayTile(mHost);
        else if (tileSpec.equals("nfc")) return new NfcTile(mHost);
        // Intent tiles.
        else if (tileSpec.startsWith(IntentTile.PREFIX)) return IntentTile.create(mHost, tileSpec);
        else if (tileSpec.startsWith(CustomTile.PREFIX)) return CustomTile.create(mHost, tileSpec);
        ///M: START@{
        else if (tileSpec.equals("screenshot")) return new ScreenShotTile(mHost);
        ///END @}
        else {
            Log.w(TAG, "Bad tile spec: " + tileSpec);
            return null;
        }


7.在frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/ScreenShotActivity.java 这个文件夹下面加这个activity

package com.android.systemui.screenshot;

import android.app.Activity;
import android.os.Bundle;
import com.android.systemui.R;

import android.content.ServiceConnection;
import android.content.ComponentName;
import android.os.Message;
import android.os.Messenger;
import android.os.Handler;
import android.os.IBinder;
import android.os.UserHandle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.content.Context;
import android.content.Intent;

public class ScreenShotActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.screenshot);

        mHandler.postDelayed(mScreenshotRunnable, 100);
    }

    private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            if (mScreenshotConnection != null) {
                ScreenShotActivity.this.unbindService(mScreenshotConnection);
                mScreenshotConnection = null;
            }
            ScreenShotActivity.this.finish();
        }
    };

    final Object mScreenshotLock = new Object();
    ServiceConnection mScreenshotConnection = null;

    final Runnable mScreenshotTimeout = new Runnable() {
        @Override public void run() {
            synchronized (mScreenshotLock) {
                mHandler.sendEmptyMessage(0);
            }
        }
    };

    private final Runnable mScreenshotRunnable = new Runnable() {
        @Override
        public void run() {
            takeScreenshot();
        }
    };

    private void takeScreenshot() {
        synchronized (mScreenshotLock) {
            if (mScreenshotConnection != null) {
                mHandler.sendEmptyMessage(0);
                return;
            }
            ComponentName cn = new ComponentName("com.android.systemui",
                    "com.android.systemui.screenshot.TakeScreenshotService");
            Intent intent = new Intent();
            intent.setComponent(cn);
            ServiceConnection conn = new ServiceConnection() {
                @Override
                public void onServiceConnected(ComponentName name, IBinder service) {
                    synchronized (mScreenshotLock) {
                        if (mScreenshotConnection != this) {
                            mHandler.sendEmptyMessage(0);
                            return;
                        }
                        Messenger messenger = new Messenger(service);
                        Message msg = Message.obtain(null, 1);
                        final ServiceConnection myConn = this;
                        Handler h = new Handler(mHandler.getLooper()) {
                            @Override
                            public void handleMessage(Message msg) {
                                synchronized (mScreenshotLock) {
                                    if (mScreenshotConnection == myConn) {
                                        ScreenShotActivity.this.unbindService(mScreenshotConnection);
                                        mScreenshotConnection = null;
                                        mHandler.removeCallbacks(mScreenshotTimeout);
                                    }
                                }
                            }
                        };
                        msg.replyTo = new Messenger(h);
                        msg.arg1 = msg.arg2 = 0;
                        try {
                            messenger.send(msg);
                        } catch (RemoteException e) {
                        }
                        mHandler.sendEmptyMessage(0);
                    }
                }
                @Override
                public void onServiceDisconnected(ComponentName name) {}
            };
            if (ScreenShotActivity.this.bindServiceAsUser(
                    intent, conn, Context.BIND_AUTO_CREATE, UserHandle.CURRENT)) {
                mScreenshotConnection = conn;
                mHandler.postDelayed(mScreenshotTimeout, 10000);
            }
        }
    }

}


8.上面加载了一个layout这可以在frameworks/base/packages/SystemUI/res/layout/screenshot.xml里面加一个layout就可以了哈





9./frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java在这里面加最后的逻辑。

 //screenshot
    private final Runnable mTakeScreenshot = new Runnable() {
        @Override
        public void run() {
            screenshot();
        }
    };

    private void screenshot() {
        if (mStatusBarWindow != null) {
            // release focus immediately to kick off focus change transition
            mStatusBarWindowManager.setStatusBarFocusable(false);

            mStatusBarWindow.cancelExpandHelper();
            mStatusBarView.collapsePanel(true /* animate */, false, 1.0f);
        }
           //这里有delay延时设置
            mHandler.postDelayed(mScreenshotRunnable, 500);
    }

    public void screenShot(){
        mHandler.post(mTakeScreenshot);
    }

    final Object mScreenshotLock = new Object();
        ServiceConnection mScreenshotConnection = null;
        final Runnable mScreenshotTimeout = new Runnable() {
        @Override public void run() {
            synchronized (mScreenshotLock) {
                if (mScreenshotConnection != null) {
                    mContext.unbindService(mScreenshotConnection);
                    mScreenshotConnection = null;
	        }
            }
        }
    };

    private final Runnable mScreenshotRunnable = new Runnable() {
        @Override
        public void run() {
            takeScreenshot();
        }
    };

    private void takeScreenshot() {
        synchronized (mScreenshotLock) {
            if (mScreenshotConnection != null) {
                mHandler.sendEmptyMessage(0);
                return;
            }
            ComponentName cn = new ComponentName("com.android.systemui",
                    "com.android.systemui.screenshot.TakeScreenshotService");
            Intent intent = new Intent();
            intent.setComponent(cn);
            ServiceConnection conn = new ServiceConnection() {
                @Override
                public void onServiceConnected(ComponentName name, IBinder service) {
                    synchronized (mScreenshotLock) {
                        if (mScreenshotConnection != this) {
                            return;
                        }
                        Messenger messenger = new Messenger(service);
                        Message msg = Message.obtain(null, 1);
                        final ServiceConnection myConn = this;
                        Handler h = new Handler(mHandler.getLooper()) {
                            @Override
                            public void handleMessage(Message msg) {
                                synchronized (mScreenshotLock) {
                                    if (mScreenshotConnection == myConn) {
                                        mContext.unbindService(mScreenshotConnection);
                                        mScreenshotConnection = null;
                                        mHandler.removeCallbacks(mScreenshotTimeout);
                                    }
                                }
                            }
                        };
                        msg.replyTo = new Messenger(h);
                        msg.arg1 = msg.arg2 = 0;
                        try {
                            messenger.send(msg);
                        } catch (RemoteException e) {
                        }
                        mHandler.sendEmptyMessage(0);
                    }
                }
                @Override
                public void onServiceDisconnected(ComponentName name) {}
            };
            if (mContext.bindServiceAsUser(
                    intent, conn, Context.BIND_AUTO_CREATE, UserHandle.CURRENT)) {
                mScreenshotConnection = conn;
                mHandler.postDelayed(mScreenshotTimeout, 10000);
            }
        }
    }

嘿嘿 大致就这样婶了。这是加了一个完整的功能,所以看着有点多。安卓8.0上SystemUI还是和7.0有点区别的。

 

你可能感兴趣的:(android)