app/src/main/java/com/egguncle/xposednavigationbar/constant/ConstantStr.java
public class ConstantStr {
    public final static String PKG_NAME = "com.egguncle.xposednavigationbar";
    public final static String SHORT_CUT_DATA = "short_cut_data";

    public final static String BACK = "back";
    public final static String NEXT_PAGE = "next";
    public final static String PREVIOUS = "previous";
    public final static String DOWN = "down";
    public final static String CLEAR_NOTIFICATION = "clear_notification";
    public final static String SCREEN_OFF = "screen_off";
    public final static String CLEAR_MEM = "clear_mem";
    public final static String QUICK_NOTICE = "quick_notice";
    public final static String LIGHT = "light";
    public final static String VOLUME = "volume";
    public final static String SMALL_POINT = "small_point";
    public final static String HOME = "home";
    public final static String START_ACTS = "start_acts";
    public final static String NEXT_PLAY = "ic_next";
    public final static String PLAY_MUSIC = "ic_play";
    public final static String PLAY_PREVIOUS = "ic_previous";

    public final static String CLOCK = "clock";

    public final static int FUNC_BACK_CODE = -2;
    public final static int FUNC_SMALL_POINT_CODE = -1;
    public final static int FUNC_DOWN_CODE = 0;
    public final static int FUNC_QUICK_NOTICE_CODE = 1;
    public final static int FUNC_SCREEN_OFF_CODE = 2;
    public final static int FUNC_CLEAR_NOTIFICATION_CODE = 3;
    public final static int FUNC_CLEAR_MEM_CODE = 4;
    public final static int FUNC_VOLUME_CODE = 5;
    public final static int FUNC_LIGHT_CODE = 6;
    public final static int FUNC_HOME_CODE = 7;
    public final static int FUNC_START_ACTS_CODE = 8;
    public final static int FUNC_PREVIOUS_PLAY_CODE = 9;
    public final static int FUNC_PLAY_MUSIC_CODE = 10;
    public final static int FUNC_NEXT_PLAY_CODE = 11;
    public final static int FUNC_WECHAT_SACNNER_CODE = 12;
    public final static int FUNC_ALIPAY_SACNNER_CODE = 13;
    public final static int FUNC_SCREEN_SHOT_CODE = 14;
    //Android自带的三个按钮
    public final static int FUNC_NAV_BACK_CODE = 15;
    public final static int FUNC_NAV_HOME_CODE = 16;
    public final static int FUNC_NAV_RECENT_CODE = 17;

    public final static int FUNC_CLIPBOARD_CODE = 18;
    public final static int FUNC_COMMAND_CODE = 19;

    public final static int FUNC_NAV_HIDE_CODE = 20;

    public static final String HOME_POINT = "home_point";
    public static final String LEFT = "left";
    public static final String RIGHT = "right";
    public static final String DISMISS = "notShow";

    public static final int IMPORTANCE_PERSISTENT = 50;
    public static final int IMPORTANCE_FOREGROUND = 100;
    public static final int IMPORTANCE_VISIBLE = 200;
    public static final int IMPORTANCE_PERCEPTIBLE = 130;
    public static final int IMPORTANCE_CANT_SAVE_STATE = 170;
    public static final int IMPORTANCE_SERVICE = 300;
    public static final int IMPORTANCE_BACKGROUND = 400;
    public static final int IMPORTANCE_EMPTY = 500;

//    public static final String IMPORTANCE_PERSISTENT_NAME = "IMPORTANCE_PERSISTENT";
//    public static final String IMPORTANCE_FOREGROUND_NAME = "IMPORTANCE_FOREGROUND";
//    public static final String IMPORTANCE_VISIBLE_NAME = "IMPORTANCE_VISIBLE";
//    public static final String IMPORTANCE_PERCEPTIBLE_NAME = "IMPORTANCE_PERCEPTIBLE";
//    public static final String IMPORTANCE_CANT_SAVE_STATE_NAME = "IMPORTANCE_CANT_SAVE_STATE";
//    public static final String IMPORTANCE_SERVICE_NAME = "IMPORTANCE_SERVICE_NAME";
//    public static final String IMPORTANCE_BACKGROUND_NAME = "IMPORTANCE_BACKGROUND";
//    public static final String IMPORTANCE_EMPTY_NAME = "IMPORTANCE_EMPTY";

    public static final String ICON_SIZE = "icon_size";

    public static final String TYPE = "type";
    public static final int CLEAR_NOTIFICATIONS = 0;
    public static final int RECENT_TASKS = 1;
    public static final int SHOW_NAVBAR = 2;
    public static final int HIDE_NAVBAR = 3;
    public static final int TAKE_SCREENSHOT = 4;
    public static final int NAVBAR_H = 5;

    public static final String NAVBAR_HEIGHT = "navbar_height";

    public static final String ACTION_COMMAND = "com.egguncle.xposednavigationbar.command";
    public static final String COMMAND_STR="command_str";
}
app/src/main/java/com/egguncle/xposednavigationbar/util/ImageUtil.java
public class ImageUtil {
    private final static String TAG = "ImageUtil";


    public static Bitmap byte2Bitmap(byte[] imgBytes) {
        return BitmapFactory.decodeByteArray(imgBytes, 0, imgBytes.length);
    }

    /**
     * 缩放图片
     *
     * @param bmByte
     * @param scale
     * @return
     */
    public static Bitmap zoomBitmap(byte[] bmByte, int scale) {
        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inJustDecodeBounds = false;
        Bitmap bm = BitmapFactory.decodeByteArray(bmByte, 0, bmByte.length, opts);

        Matrix matrix = new Matrix();
        matrix.postScale((float) (scale / 100.0), (float) (scale / 100.0));
        Bitmap bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
        return bitmap;
    }


    public static Bitmap zoomBitmap(String imgPath, int scale) {
        try {
            BitmapFactory.Options opts = new BitmapFactory.Options();
            opts.inJustDecodeBounds = false;
            Bitmap bm;

            bm = BitmapFactory.decodeFile(imgPath);

            Matrix matrix = new Matrix();
            matrix.postScale((float) (scale / 100.0), (float) (scale / 100.0));
            Bitmap bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
            return bitmap;
        } catch (Exception e) {
            return null;
        }
    }

    public static Bitmap zommBitmap(Bitmap bm, int scale) {
        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inJustDecodeBounds = false;

        Matrix matrix = new Matrix();
        matrix.postScale((float) (scale / 100.0), (float) (scale / 100.0));
        Bitmap bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
        return bitmap;
    }

    /**
     * @param data
     * @return 图片路径
     */
    public static String handleImageOnKitKat(Intent data) {
        String imagePath = "";
        Log.i(TAG, "handleImageOnKitKat: ");

        Uri uri = data.getData();
        if (DocumentsContract.isDocumentUri(MyApplication.getContext(), uri)) {
            //如果是document类型的uri，则通过document id处理
            String docId = DocumentsContract.getDocumentId(uri);
            if ("com.android.providers.media.documents".equals(uri.getAuthority())) {
                String id = docId.split(":")[1];//解析出数字格式的ID
                String selection = MediaStore.Images.Media._ID + "=" + id;
                imagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection);
            } else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) {
                Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(docId));
                imagePath = getImagePath(contentUri, null);
            }
        } else if ("content".equalsIgnoreCase(uri.getScheme())) {
            //如果是content类型的uri，则使用普通的方式处理
            imagePath = getImagePath(uri, null);
        } else if ("file".equalsIgnoreCase(uri.getScheme())) {
            //如果是file类型的uri，直接获取图片路径即可
            imagePath = uri.getPath();
        }
        return imagePath;
    }

    private static String getImagePath(Uri uri, String selection) {
        String path = null;
        //通过Uri和selection来获取图片的真实路径
        Cursor cursor = MyApplication.getContext().getContentResolver().query(uri, null, selection, null, null);
        if (cursor != null) {
            if (cursor.moveToFirst()) {
                path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
            }
            cursor.close();
        }

        return path;
    }

    public static Bitmap handleImageEffect(Bitmap bm, float lum) {
        Bitmap bmp = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bmp);
        Paint paint = new Paint();

        ColorMatrix lumMatrix = new ColorMatrix();
        lumMatrix.setScale(lum, lum, lum, 1);

        ColorMatrix imageMatrix = new ColorMatrix();
        imageMatrix.postConcat(lumMatrix);

        paint.setColorFilter(new ColorMatrixColorFilter(imageMatrix));
        canvas.drawBitmap(bm, 0, 0, paint);

        return bmp;
    }

    public static Bitmap drawableToBitmap(Drawable drawable) {
        int w = drawable.getIntrinsicWidth();
        int h = drawable.getIntrinsicHeight();
        Bitmap.Config config =
                drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
                        : Bitmap.Config.RGB_565;
        Bitmap bitmap = Bitmap.createBitmap(w, h, config);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, w, h);
        drawable.draw(canvas);

        return bitmap;
    }
}
app/src/main/java/com/egguncle/xposednavigationbar/hook/btnFunc/BtnScreenShot.java
public class BtnScreenShot extends ScreenShot {

    @Override
    public void screenshot(Context context) {
        context.sendBroadcast(intent);
    }
}
app/src/main/java/com/egguncle/xposednavigationbar/hook/hookutil/DataHook.java
public class DataHook {
    //用于加载图片资源
    public static Map<Integer, byte[]> mapImgRes = new HashMap<>();
    public static int iconScale;
    public static boolean expandStatusBarWithRoot;
    //用于获取保存的快捷按键设置
    public static List<ShortCut> shortCutList;
    public static int homePointPosition;

    //内存清理强度
    public static int clearMenLevel;
    public static boolean chameleonNavbar;
    public static int navbarHeight;
    public static boolean rootDown;
    public static boolean vibrate;
    public static boolean navbarOpt;
    public static boolean goHomeAfterClick;


    public static void init(IXposedHookZygoteInit.StartupParam startupParam) throws Throwable {
        XSharedPreferences pre = new XSharedPreferences(BuildConfig.APPLICATION_ID, "xpnavbar");
        pre.makeWorldReadable();

        String json = pre.getString(ConstantStr.SHORT_CUT_DATA, "");
        XpLog.i("short_cut_data " + json);
        expandStatusBarWithRoot = pre.getBoolean(SPUtil.ROOT_DOWN, false);
        clearMenLevel = pre.getInt(SPUtil.CLEAR_MEM_LEVEL, 200);
        //获取主导行栏小点的位置
        homePointPosition = pre.getInt(ConstantStr.HOME_POINT, 0);
        chameleonNavbar = pre.getBoolean(SPUtil.CHAMELEON_NAVBAR, false);
        rootDown = pre.getBoolean(SPUtil.ROOT_DOWN, false);
        vibrate = pre.getBoolean(SPUtil.NAVBAR_VIBRATE, false);
        //获取快捷按钮设置数据
        Gson gson = new Gson();
        //在第一次激活重新启动的时候，可能因为没有设置任何快捷按钮，导致这里报错
        try {
            shortCutList = gson.fromJson(json, ShortCutData.class).getData();
        } catch (Exception e) {
            shortCutList = new ArrayList<>();
        }

        //获取图片缩放大小
        iconScale = pre.getInt(ConstantStr.ICON_SIZE, 40);

        navbarHeight = pre.getInt(SPUtil.NAVBAR_HEIGHT, 100);

        navbarOpt = pre.getBoolean(SPUtil.NAVBAR_HEIGHT_OPT, false);

        goHomeAfterClick = pre.getBoolean(SPUtil.GO_HOME_AFTER_CLICK, false);

        //加载图片资源文件
        Resources res = XModuleResources.createInstance(startupParam.modulePath, null);
        byte[] backImg = XposedHelpers.assetAsByteArray(res, "back.png");
        byte[] clearMenImg = XposedHelpers.assetAsByteArray(res, "clear_mem.png");
        byte[] clearNotificationImg = XposedHelpers.assetAsByteArray(res, "clear_notification.png");
        byte[] downImg = XposedHelpers.assetAsByteArray(res, "down.png");
        byte[] lightImg = XposedHelpers.assetAsByteArray(res, "light.png");
        byte[] quickNoticesImg = XposedHelpers.assetAsByteArray(res, "quick_notices.png");
        byte[] screenOffImg = XposedHelpers.assetAsByteArray(res, "screenoff.png");
        //  byte[] upImg = XposedHelpers.assetAsByteArray(res, "up.png");
        byte[] volume = XposedHelpers.assetAsByteArray(res, "volume.png");
        byte[] smallPonit = XposedHelpers.assetAsByteArray(res, "small_point.png");
        byte[] home = XposedHelpers.assetAsByteArray(res, "ic_home.png");
        byte[] startActs = XposedHelpers.assetAsByteArray(res, "start_acts.png");
        byte[] playMusic = XposedHelpers.assetAsByteArray(res, "ic_music.png");
        byte[] pauseMusic = XposedHelpers.assetAsByteArray(res, "ic_pause.png");
        byte[] previousMusic = XposedHelpers.assetAsByteArray(res, "ic_previous.png");
        byte[] nextMusic = XposedHelpers.assetAsByteArray(res, "ic_next.png");
        byte[] scanWeChat = XposedHelpers.assetAsByteArray(res, "wechat_qr.png");
        byte[] scanAlipay = XposedHelpers.assetAsByteArray(res, "alipay_qr.png");
        byte[] screenshot = XposedHelpers.assetAsByteArray(res, "ic_image.png");
        byte[] navBack = XposedHelpers.assetAsByteArray(res, "ic_sysbar_back.png");
        byte[] navHome = XposedHelpers.assetAsByteArray(res, "ic_sysbar_home.png");
        byte[] navRecent = XposedHelpers.assetAsByteArray(res, "ic_sysbar_recent.png");
        byte[] clipBoard = XposedHelpers.assetAsByteArray(res, "ic_clipboard.png");
        byte[] command = XposedHelpers.assetAsByteArray(res, "ic_command.png");
        byte[] navHide = XposedHelpers.assetAsByteArray(res, "ic_nav_down.png");

        mapImgRes.put(ConstantStr.FUNC_BACK_CODE, backImg);
        mapImgRes.put(ConstantStr.FUNC_CLEAR_MEM_CODE, clearMenImg);
        mapImgRes.put(ConstantStr.FUNC_CLEAR_NOTIFICATION_CODE, clearNotificationImg);
        mapImgRes.put(ConstantStr.FUNC_DOWN_CODE, downImg);
        mapImgRes.put(ConstantStr.FUNC_LIGHT_CODE, lightImg);
        mapImgRes.put(ConstantStr.FUNC_QUICK_NOTICE_CODE, quickNoticesImg);
        mapImgRes.put(ConstantStr.FUNC_SCREEN_OFF_CODE, screenOffImg);
        //  mapImgRes.put(ConstantStr.UP, upImg);
        mapImgRes.put(ConstantStr.FUNC_VOLUME_CODE, volume);
        mapImgRes.put(ConstantStr.FUNC_SMALL_POINT_CODE, smallPonit);
        mapImgRes.put(ConstantStr.FUNC_HOME_CODE, home);
        mapImgRes.put(ConstantStr.FUNC_START_ACTS_CODE, startActs);
        mapImgRes.put(ConstantStr.FUNC_PLAY_MUSIC_CODE, playMusic);
        mapImgRes.put(ConstantStr.FUNC_NEXT_PLAY_CODE, nextMusic);
        mapImgRes.put(ConstantStr.FUNC_PREVIOUS_PLAY_CODE, previousMusic);
        mapImgRes.put(ConstantStr.FUNC_WECHAT_SACNNER_CODE, scanWeChat);
        mapImgRes.put(ConstantStr.FUNC_ALIPAY_SACNNER_CODE, scanAlipay);
        mapImgRes.put(ConstantStr.FUNC_SCREEN_SHOT_CODE, screenshot);
        mapImgRes.put(ConstantStr.FUNC_NAV_BACK_CODE, navBack);
        mapImgRes.put(ConstantStr.FUNC_NAV_HOME_CODE, navHome);
        mapImgRes.put(ConstantStr.FUNC_NAV_RECENT_CODE, navRecent);
        mapImgRes.put(ConstantStr.FUNC_CLIPBOARD_CODE, clipBoard);
        mapImgRes.put(ConstantStr.FUNC_COMMAND_CODE, command);
        mapImgRes.put(ConstantStr.FUNC_NAV_HIDE_CODE, navHide);
    }

}
app/src/main/java/com/egguncle/xposednavigationbar/hook/btnFunc/BtnClearBackground.java
public class BtnClearBackground extends ClearBackground {

    @Override
    protected void clearBackground(Context context) {
        XpLog.i("clear mem level is " + DataHook.clearMenLevel);
        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        ArrayList<String> pkgNames = new ArrayList<>();
        List<ActivityManager.RunningAppProcessInfo> processInfoList = am.getRunningAppProcesses();
        if (processInfoList != null && processInfoList.size() != 0) {
            for (int i = 0; i < processInfoList.size(); i++) {
                ActivityManager.RunningAppProcessInfo processInfo = processInfoList.get(i);
                if (processInfo.importance > DataHook.clearMenLevel) {
                    String[] pkgList = processInfo.pkgList;
                    for (String pkgName : pkgList) {
                        if (pkgName.contains("com.android")) {
                            continue;
                        }
                        pkgNames.add(pkgName);
                    }
                }
            }
        }
        Intent intent = new Intent();
        intent.setAction(ACTION_FORCE_STOP_AC);
        intent.putStringArrayListExtra("data", pkgNames);
        context.sendBroadcast(intent);
        XpLog.i("has send pkgnames to kill");
    }

}
app/src/main/java/com/egguncle/xposednavigationbar/hook/btnFunc/BtnStatusBarController.java
public class BtnStatusBarController extends StatusBarController {

    private final static String STATUS_BAR = "statusbar";

    @Override
    protected void expandAllStatusBar(Context context) {
        if (DataHook.rootDown) {
            //如果在6.0环境下，尝试申请root权限来解决通知栏展开缓慢的问题
            if (Build.VERSION.SDK_INT == Build.VERSION_CODES.M && requestRoot()) {
                //申请成功后会模拟手势进行下拉
                //如果失败了，就按照普通的方式下拉
                //  expandAllStatusBarWithOutRoot(context);
            } else {
                expandAllStatusBarWithOutRoot(context);
            }
        } else {
            expandAllStatusBarWithOutRoot(context);
        }
    }

    @Override
    protected void expandAllStatusBarWithOutRoot(Context context) {
        Object statusBarManager = context.getSystemService(STATUS_BAR);
        XposedHelpers.callMethod(statusBarManager, "expandSettingsPanel");
    }

    @Override
    protected void expandStatusBar(Context context) {
        Object statusBarManager = context.getSystemService(STATUS_BAR);
        XposedHelpers.callMethod(statusBarManager, "expandNotificationsPanel");
    }

    @Override
    protected boolean requestRoot() {
        //先申请root权限
        Process process = null;
        boolean result = false;
        try {
            // XpLog.i("申请root");
            process = Runtime.getRuntime().exec("su");
            result = true;
            // XpLog.i("申请成功");
            final Process finalProcess = process;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    // boolean result = false;
                    DataOutputStream dataOutputStream = null;
                    try {
                        dataOutputStream = new DataOutputStream(finalProcess.getOutputStream());
                        // 模拟手势下拉 这个地方模拟点击有写别的rom会点击到别的快捷开关，所以做两次下拉
                        String command = "input swipe 100 10 100 1000 200 \n";
                        // String command2 = "input tap 200 150 \n";
                        dataOutputStream.write(command.getBytes(Charset.forName("utf-8")));
                        SystemClock.sleep(200);
                        dataOutputStream.write(command.getBytes(Charset.forName("utf-8")));
                        dataOutputStream.flush();
                        dataOutputStream.writeBytes("exit\n");
                        dataOutputStream.flush();
                        finalProcess.waitFor();


                    } catch (Exception e) {

                    } finally {
                        try {
                            if (dataOutputStream != null) {
                                dataOutputStream.close();
                            }

                        } catch (IOException e) {

                        }
                    }

                }
            }).start();
        } catch (IOException e) {
            e.printStackTrace();
            XpLog.i("申请 失败");
        }

        return result;
    }
}
app/src/main/java/com/egguncle/xposednavigationbar/hook/btnFunc/BtnBackLight.java
public class BtnBackLight extends LightAndVolumeController {

    public BtnBackLight() {
        super(LightAndVolumeController.LIGHT);
    }

    @Override
    protected void control(Context context, int value) {
        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        XposedHelpers.callMethod(pm,"setBacklightBrightness",value);
    }
}
app/src/main/java/com/egguncle/xposednavigationbar/hook/btnFunc/BtnVolume.java
public class BtnVolume extends LightAndVolumeController {
    public BtnVolume(){
        super(LightAndVolumeController.VOLUME);
    }

    @Override
    protected void control(Context context, int value) {
        AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        //调整媒体声言，不播放声言也不振动
        am.setStreamVolume(AudioManager.STREAM_MUSIC, value, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
    }
}
app/src/main/java/com/egguncle/xposednavigationbar/hook/btnFunc/BtnAlipayScanner.java
public class BtnAlipayScanner extends ScannerQRcode {

    @Override
    public void scanQR(final Context context) {
        try {
            Uri uri = Uri.parse("alipayqr://platformapi/startapp?saId=10000007");
            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
            context.startActivity(intent);
        } catch (Exception e) {
            XpLog.i(e.getMessage());
        }
    }
}
app/src/main/java/com/egguncle/xposednavigationbar/hook/btnFunc/BtnNavBarGoHome.java
public class BtnNavBarGoHome extends GoHomeNavBar {
    public BtnNavBarGoHome(ViewPager viewPager) {
        super(viewPager);
    }

    @Override
    protected void goHomeNavBar(ViewPager viewPager) {
        viewPager.setCurrentItem(1);
    }
}
app/src/main/java/com/egguncle/xposednavigationbar/model/ShortCut.java
public class ShortCut implements Parcelable{
    //快捷小功能的名字对应的编码
    private int code;
//    //快捷小功能的标识符
//    private String shortCutName;
    //是否开启了这个功能
    private boolean open;
    //第几页
    private int page;
    //该页的第几个位置
    private int postion;

    //自定义图标路径
    private String iconPath;

    //如果是shell快捷指令，则应该还有一个指令内容
    private String shellStr;

    public ShortCut(){}

    protected ShortCut(Parcel in) {
        code = in.readInt();
        open = in.readByte() != 0;
        page = in.readInt();
        postion = in.readInt();
        iconPath = in.readString();
        shellStr = in.readString();
    }

    public static final Creator<ShortCut> CREATOR = new Creator<ShortCut>() {
        @Override
        public ShortCut createFromParcel(Parcel in) {
            return new ShortCut(in);
        }

        @Override
        public ShortCut[] newArray(int size) {
            return new ShortCut[size];
        }
    };

    public int getPage() {
        return page;
    }

    public void setPage(int page) {
        this.page = page;
    }

    public int getPostion() {
        return postion;
    }

    public void setPostion(int postion) {
        this.postion = postion;
    }

    public int getCode() {return code;}

    public void setCode(int code) {this.code = code;}

    public boolean isOpen() {
        return open;
    }

    public void setOpen(boolean open) {
        this.open = open;
    }

    public String getShellStr() {
        return shellStr;
    }

    public void setShellStr(String shellStr) {
        this.shellStr = shellStr;
    }
    public String getIconPath() {
        return iconPath;
    }

    public void setIconPath(String iconPath) {
        this.iconPath = iconPath;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeInt(code);
        parcel.writeByte((byte) (open ? 1 : 0));
        parcel.writeInt(page);
        parcel.writeInt(postion);
        parcel.writeString(iconPath);
        parcel.writeString(shellStr);
    }
}
app/src/main/java/com/egguncle/xposednavigationbar/hook/btnFunc/BtnOpenActPanel.java
public class BtnOpenActPanel extends StartActPanel {

    @Override
    protected void openActPanel(Context context) {
        Intent intent = new Intent(ACTION_START_ACT);
        //使用这种启动标签，可以避免在打开软件本身以后再通过快捷键呼出备忘对话框时仍然显示软件的界面的bug
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        context.startActivity(intent);
    }

    @Override
    protected void closeActPanel(Context context) {
        Intent intent = new Intent();
        intent.setAction(XpNavBarAction.ACT_CLOSE_ACT_PANEL);
        context.sendBroadcast(intent);
    }
}
app/src/main/java/com/egguncle/xposednavigationbar/hook/btnFunc/BtnStartCommand.java
public class BtnStartCommand extends StartCommand {
    private Intent mIntent;

    public BtnStartCommand(String command) {
        super(command);
        mIntent = new Intent();
        mIntent.setAction(ConstantStr.ACTION_COMMAND);
    }

    @Override
    protected void startCommand(String command, Context context) {
        mIntent.putExtra(COMMAND_STR, command);
        XpLog.i(command);
        context.sendBroadcast(mIntent);
    }
}
app/src/main/java/com/egguncle/xposednavigationbar/hook/btnFunc/BtnQuickNotice.java
public class BtnQuickNotice extends QuickNotification{
    @Override
    protected void quickNotification(Context context) {
        Intent intent = new Intent(ACTION_QUICK_NOTICE);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        context.startActivity(intent);
    }

}
app/src/main/java/com/egguncle/xposednavigationbar/hook/btnFunc/BtnWeChatScanner.java
public class BtnWeChatScanner extends ScannerQRcode{

    @Override
    public void scanQR(Context context) {
        String cmd="am start -n com.tencent.mm/com.tencent.mm.plugin.scanner.ui.BaseScanUI";
        try {
            Process p = Runtime.getRuntime().exec(cmd);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
app/src/main/java/com/egguncle/xposednavigationbar/hook/btnFunc/BtnClearAllNotifications.java
public class BtnClearAllNotifications extends ClearAllNotifications{

    @Override
    public void clearAllNotifications(Context context) {
        context.sendBroadcast(intent);
        //方法执行后，不会马上清除所有的消息，而是在通知栏下拉，通知内容变得可见后才清除。
        //所以在这里调用一次下拉通知栏的方法
        //再收起通知栏
        try {
            Object statusBarManager = context.getSystemService("statusbar");
            Method expand;
            expand = statusBarManager.getClass().getMethod("expandNotificationsPanel");
            expand.invoke(statusBarManager);
        } catch (Exception localException) {
            localException.printStackTrace();
        }
    }
}
app/src/main/java/com/egguncle/xposednavigationbar/hook/btnFunc/BtnScreenOff.java
public class BtnScreenOff extends ScreenOff{

    @Override
    protected void screenOff(Context context) {
        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        XposedHelpers.callMethod(pm,"goToSleep",SystemClock.uptimeMillis());
    }

    @Override
    protected void showPowerMenu(Context context) {
        Instrumentation mInst = new Instrumentation();
        KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_POWER);
        mInst.sendKeySync(keyEvent);
    }
}
app/src/main/java/com/egguncle/xposednavigationbar/hook/btnFunc/BtnNavClipboard.java
public class BtnNavClipboard extends NavClipboard {

    @Override
    protected void getClipboadrData(Context context) {
        ArrayList<String> data = MyClipBoard.getClipboardData();
        for (String s : data) {
            XpLog.i(s);
        }
        Intent intent = new Intent(ACTION_CLIPBOARD);
        intent.putStringArrayListExtra("data", data);
        //使用这种启动标签，可以避免在打开软件本身以后再通过快捷键呼出备忘对话框时仍然显示软件的界面的bug
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        context.startActivity(intent);
    }

    @Override
    protected void showClipboardData() {

    }
}
app/src/main/java/com/egguncle/xposednavigationbar/hook/btnFunc/BtnMusicController.java
public class BtnMusicController extends MusicController {

    private Instrumentation mInst;

    public BtnMusicController(int type) {
        super(type);
        mInst = new Instrumentation();
    }

    @Override
    protected void nextMusic() {
        mInst.sendKeyDownUpSync(KeyEvent.KEYCODE_MEDIA_NEXT);
    }

    @Override
    protected void startOrPauseMusic() {
        if (isPlaying) {
            mInst.sendKeyDownUpSync(KeyEvent.KEYCODE_MEDIA_PAUSE);
            isPlaying = false;
        } else {
            mInst.sendKeyDownUpSync(KeyEvent.KEYCODE_MEDIA_PLAY);
            isPlaying = true;
        }
    }

    @Override
    protected void previousMusic() {
        mInst.sendKeyDownUpSync(KeyEvent.KEYCODE_MEDIA_PREVIOUS);
    }
}
app/src/main/java/com/egguncle/xposednavigationbar/hook/btnFunc/BtnsNavbar.java
public class BtnsNavbar extends NavBarBtns {

    private Instrumentation mInst;

    public BtnsNavbar(int type) {
        super(type);
        mInst = new Instrumentation();
    }

    @Override
    protected void goBack() {
        mInst.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
    }

    @Override
    protected void goHome() {
        mInst.sendKeyDownUpSync(KeyEvent.KEYCODE_HOME);
    }

    @Override
    protected void longHome() {
        KeyEvent keyEvent = new KeyEvent(KeyEvent.FLAG_LONG_PRESS, KeyEvent.KEYCODE_HOME);
        mInst.sendKeySync(keyEvent);
    }

    @Override
    protected void goRecent(Context context) {
        context.sendBroadcast(intent);
    }

    @Override
    protected void hide(Context context) {
        context.sendBroadcast(intent);
    }

    @Override
    protected void show() {

    }
}


Question: import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.graphics.drawable.RippleDrawable;
import android.support.v4.view.ViewPager;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import com.egguncle.xposednavigationbar.constant.ConstantStr;
import com.egguncle.xposednavigationbar.hook.btnFunc.BtnAlipayScanner;
import com.egguncle.xposednavigationbar.hook.btnFunc.BtnBackLight;
import com.egguncle.xposednavigationbar.hook.btnFunc.BtnClearAllNotifications;
import com.egguncle.xposednavigationbar.hook.btnFunc.BtnClearBackground;
import com.egguncle.xposednavigationbar.hook.btnFunc.BtnMusicController;
import com.egguncle.xposednavigationbar.hook.btnFunc.BtnNavBarGoHome;
import com.egguncle.xposednavigationbar.hook.btnFunc.BtnNavClipboard;
import com.egguncle.xposednavigationbar.hook.btnFunc.BtnOpenActPanel;
import com.egguncle.xposednavigationbar.hook.btnFunc.BtnQuickNotice;
import com.egguncle.xposednavigationbar.hook.btnFunc.BtnScreenOff;
import com.egguncle.xposednavigationbar.hook.btnFunc.BtnScreenShot;
import com.egguncle.xposednavigationbar.hook.btnFunc.BtnStartCommand;
import com.egguncle.xposednavigationbar.hook.btnFunc.BtnStatusBarController;
import com.egguncle.xposednavigationbar.hook.btnFunc.BtnVolume;
import com.egguncle.xposednavigationbar.hook.btnFunc.BtnWeChatScanner;
import com.egguncle.xposednavigationbar.hook.btnFunc.BtnsNavbar;
import com.egguncle.xposednavigationbar.hook.hookutil.DataHook;
import com.egguncle.xposednavigationbar.model.ShortCut;
import com.egguncle.xposednavigationbar.util.ImageUtil;
import java.util.Map;
/*
 *     Navigation bar function expansion module
 *     Copyright (C) 2017 egguncle cicadashadow@gmail.com
 *
 *     This program is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public License
 *     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.egguncle.xposednavigationbar.hook.util;




/**
 * Created by egguncle on 17-6-10.
 */

public class BtnFuncFactory {
    private ViewPager mViewPager;
    //用于加载图片资源
    private Map<Integer, byte[]> mMapImgRes;
    private ViewGroup mllExtPage;

    public BtnFuncFactory(ViewPager viewPager, ViewGroup llExtPage) {
        mMapImgRes = DataHook.mapImgRes;
        mViewPager = viewPager;
        mllExtPage = llExtPage;

        if (mMapImgRes == null) {
            XpLog.i("map img res is null");
        }
    }

    public BtnFuncFactory(ViewGroup exNavbar) {
        mllExtPage = exNavbar;
        mMapImgRes = DataHook.mapImgRes;
    }


    public View.OnClickListener getBtnFuncOfName(ShortCut sc) {
        switch (sc.getCode()) {
            case ConstantStr.FUNC_DOWN_CODE:
                return new BtnStatusBarController();
            case ConstantStr.FUNC_QUICK_NOTICE_CODE:
Answer:                 return new BtnQuickNotice();