1. 程式人生 > >Android手勢密碼原理分析

Android手勢密碼原理分析

在上一篇介紹了手勢密碼的使用,這一篇將主要介紹手勢密碼的原理,手勢密碼的功能主要是由自定義PatternLockView實現的。那咱這就一步一步來揭開PatternLockView的面紗。

效果圖

這裡寫圖片描述這裡寫圖片描述這裡寫圖片描述

步驟

第一步

自定義PatternLockView繼承View,重寫兩個構造方法,一個在xml中定義會呼叫,一個在java程式碼中建立物件會呼叫。但不管怎麼定義,都會走到這個構造中。

public PatternLockView(Context context, AttributeSet attrs) {
        super(context, attrs);

        TypedArray typedArray = context.obtainStyledAttributes
(attrs, R.styleable.PatternLockView); try { sDotCount = typedArray.getInt(R.styleable.PatternLockView_dotCount, DEFAULT_PATTERN_DOT_COUNT); mPathWidth = (int) typedArray.getDimension(R.styleable.PatternLockView_pathWidth, ResourceUtils.getDimensionInPx
(getContext(), R.dimen.pattern_lock_path_width)); mNormalDotStateColor = typedArray.getColor(R.styleable.PatternLockView_normalDotStateColor, ResourceUtils.getColor(getContext(), R.color.white)); mCorrectDotStateColor = typedArray.getColor(R.styleable.PatternLockView
_correctDotStateColor, ResourceUtils.getColor(getContext(), R.color.white)); mCorrectDotStrokeColor = typedArray.getColor(R.styleable.PatternLockView_correctDotStrokeStateColor, ResourceUtils.getColor(getContext(), R.color.white)); mCorrectLineStateColor = typedArray.getColor(R.styleable.PatternLockView_correctLineStateColor, ResourceUtils.getColor(getContext(), R.color.white)); mWrongLineStateColor = typedArray.getColor(R.styleable.PatternLockView_wrongLineStateColor, ResourceUtils.getColor(getContext(), R.color.white)); mWrongDotStateColor = typedArray.getColor(R.styleable.PatternLockView_wrongDotStateColor, ResourceUtils.getColor(getContext(), R.color.white)); mWrongDotStrokeStateColor = typedArray.getColor(R.styleable.PatternLockView_wrongDotStrokeStateColor, ResourceUtils.getColor(getContext(), R.color.white)); mDotNormalSize = (int) typedArray.getDimension(R.styleable.PatternLockView_dotNormalSize, ResourceUtils.getDimensionInPx(getContext(), R.dimen.pattern_lock_dot_size)); mDotSelectedSize = (int) typedArray.getDimension(R.styleable.PatternLockView_dotSelectedSize, ResourceUtils.getDimensionInPx(getContext(), R.dimen.pattern_lock_dot_selected_size)); mDotAnimationDuration = typedArray.getInt(R.styleable.PatternLockView_dotAnimationDuration, DEFAULT_DOT_ANIMATION_DURATION); } finally { typedArray.recycle(); } //獲取繪製點的個數 mPatternSize = sDotCount * sDotCount; //存放選中的點 mPattern = new ArrayList<>(mPatternSize); //二維陣列 選中點時置為true mPatternDrawLookup = new boolean[sDotCount][sDotCount]; //二維陣列 存放點物件 mDotStates = new DotState[sDotCount][sDotCount]; //通過迴圈的方式,建立點物件,並對點初始化大小 for (int i = 0; i < sDotCount; i++) { for (int j = 0; j < sDotCount; j++) { mDotStates[i][j] = new DotState(); mDotStates[i][j].mSize = mDotNormalSize; } } //存放監聽物件 mPatternListeners = new ArrayList<>(); initView(); }

這裡主要拿到我們自定義的點的數量 點的顏色 線的顏色 線的寬度等資訊,建立了存放選中點的集合 存放監聽物件的集合和兩個二維陣列及點物件。

再來看下initView()方法

private void initView() {
        //設定View可點選
        setClickable(true);

        //設定點與點連線畫筆
        mPathPaint = new Paint();
        mPathPaint.setAntiAlias(true);
        mPathPaint.setDither(true);
        mPathPaint.setColor(mCorrectLineStateColor);
        mPathPaint.setStyle(Paint.Style.STROKE);
        //當畫筆樣式為STROKE或FILL_OR_STROKE時,設定筆刷的圖形樣式,如圓形樣式Cap.ROUND,或方形樣式Cap.SQUARE
        mPathPaint.setStrokeJoin(Paint.Join.ROUND);
        //設定繪製時各圖形的結合方式,如平滑效果等
        mPathPaint.setStrokeCap(Paint.Cap.ROUND);
        mPathPaint.setStrokeWidth(mPathWidth);

        //設定畫點的畫筆
        mDotPaint = new Paint();
        mDotPaint.setAntiAlias(true);
        mDotPaint.setDither(true);

        //設定點外環的畫筆
        mRingPaint = new Paint();
        mRingPaint.setAntiAlias(true);
        mRingPaint.setDither(true);

        //設定點放大縮小動畫(用於隱藏模式)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !isInEditMode()) {
            mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(
                    getContext(), android.R.interpolator.fast_out_slow_in);
            mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(
                    getContext(), android.R.interpolator.linear_out_slow_in);
        }
    }

這裡主要對各個畫筆做了初始化工作,也可以通過Java程式碼進行更改,初始化工作完成後,就要捕捉手勢了。

第二步

通過onTouchEvent()方法獲取手勢座標

@Override
public boolean onTouchEvent(MotionEvent event) {
        //判斷View是否可用
        if (!mInputEnabled || !isEnabled()) {
            return false;
        }

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                handleActionDown(event);
                return true;
            case MotionEvent.ACTION_UP:
                handleActionUp(event);
                return true;
            case MotionEvent.ACTION_MOVE:
                handleActionMove(event);
                return true;
            case MotionEvent.ACTION_CANCEL:
                mPatternInProgress = false;
                resetPattern();
                notifyPatternCleared();
                return true;
        }
        return false;
    }

這裡對手指的按下 移動 擡起 取消都做了判斷
取消的操作比較簡單,就是重置各個狀態

下邊分別來看下按下 移動 擡起

handleActionDown按下方法

private void handleActionDown(MotionEvent event) {
        //每次按下都重置下狀態
        resetPattern();
        //獲取手指按下的座標,以View區域的左上頂點為(0,0)座標
        float x = event.getX();
        float y = event.getY();
        //通過detectAndAddHit方法判斷首次按下是否觸碰到點
        Dot hitDot = detectAndAddHit(x, y);

        //如果觸碰到點,則改變狀態,開始畫選中點顏色和與點的連線
        //如果沒有觸碰上,則不畫線(通過mPatternInProgress狀態控制)
        if (hitDot != null) {
            mPatternInProgress = true;
            mPatternViewMode = CORRECT;
            notifyPatternStarted();
        } else {
            mPatternInProgress = false;
            notifyPatternCleared();
        }
        //如果首次觸碰到點,則進行區域性重新整理
        if (hitDot != null) {
            //獲取選中點的中心座標
            float startX = getCenterXForColumn(hitDot.mColumn);
            float startY = getCenterYForRow(hitDot.mRow);

            float widthOffset = mViewWidth / 2f;
            float heightOffset = mViewHeight / 2f;

            // 區域性重新整理其實沒多大用,在onDraw裡邊還是所有程式碼都走
            invalidate((int) (startX - widthOffset),
                    (int) (startY - heightOffset),
                    (int) (startX + widthOffset), (int) (startY + heightOffset));
        }
        //把首次按下的座標賦值給mInProgressX mInProgressY
        //當選中時可開始畫線
        mInProgressX = x;
        mInProgressY = y;
    }

按下操作主要是獲取首次按下座標,並通過座標拿到是否觸碰到某一個點上,如果觸碰到點上,則改變點的顏色並開始畫點與手指的連線。

handleActionMove移動方法

private void handleActionMove(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
        Dot hitDot = detectAndAddHit(x, y);
        int patternSize = mPattern.size();
        //手指按下時沒有選中點,當滑動時,滑動到點上進入此判斷語句
        //改變mPatternInProgress mPatternViewMode狀態,重畫選中點和外環的顏色及開始畫與點的連線
        if (hitDot != null && patternSize == 1) {
            mPatternInProgress = true;
            mPatternViewMode = CORRECT;
            notifyPatternStarted();
        }

        mInProgressX = event.getX();
        mInProgressY = event.getY();
        //簡單粗暴 重新繪製
        invalidate();
    }

移動操作主要是根據不斷移動的座標,判斷是否觸碰到點上,如果觸碰上了就新增到選中點的集合內,並重畫選中點和外環的顏色及開始畫與點的連線。

handleActionUp擡起方法

private void handleActionUp(MotionEvent event) {
        // 判斷手勢集合中是否有選中的點
        if (!mPattern.isEmpty()) {
            //重置狀態 阻止畫最後一個點與手指之間的連線
            mPatternInProgress = false;
            notifyPatternDetected();
            //擡起的時候再繪製一次
            invalidate();
        }
    }

擡起操作主要是判斷存放點的集合是否為空,如果不為空,則重置狀態,阻止畫最後一個點與手指之間的連線。

detectAndAddHit方法

/**
* 根據x,y座標確定是否點選到點上
*/
private Dot detectAndAddHit(float x, float y) {
        //通過checkForNewHit判斷座標是否在一個點上
        final Dot dot = checkForNewHit(x, y);
        //如果在則返回點 如果不在則返回null
        if (dot != null) {
            Dot fillInGapDot = null;
            //拿到初始化定義存放選中點的集合
            final ArrayList<Dot> pattern = mPattern;
            if (!pattern.isEmpty()) {
                //拿到集合中最後一個點
                Dot lastDot = pattern.get(pattern.size() - 1);
                int dRow = dot.mRow - lastDot.mRow;
                int dColumn = dot.mColumn - lastDot.mColumn;

                int fillInRow = lastDot.mRow;
                int fillInColumn = lastDot.mColumn;

                //重新計算行
                /**
                 * 重新計算行
                 * 例如:從(0,1)直接到(2,1),想跳過(1,1)時,則通過此方法把第一行新增進去
                 */
                if (Math.abs(dRow) == 2 && Math.abs(dColumn) != 1) {
                    fillInRow = lastDot.mRow + ((dRow > 0) ? 1 : -1);
                }
                //重新計算列
                if (Math.abs(dColumn) == 2 && Math.abs(dRow) != 1) {
                    fillInColumn = lastDot.mColumn + ((dColumn > 0) ? 1 : -1);
                }
                //
                fillInGapDot = Dot.of(fillInRow, fillInColumn);
            }

            /**
             * 例如:從(0,1)直接到(2,1),想跳過(1,1)時,則通過此方法把第一行新增進去
             */
            if (fillInGapDot != null
                    && !mPatternDrawLookup[fillInGapDot.mRow][fillInGapDot.mColumn]) {
                addCellToPattern(fillInGapDot);
            }
            /**
             * 如果中間跳過一個點則先新增跳過的點
             * 如果沒有則新增選中的點
             */
            addCellToPattern(dot);
            /**
             * 判斷是否震動
             */
            if (mEnableHapticFeedback) {
                performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
                        HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING
                                | HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
            }
            return dot;
        }
        return null;
    }

detectAndAddHit方法主要是根據座標拿到點,並判斷前一個點與現在點中間是否還有必須經過但還有新增的點,如果有則優先新增中間點,如果沒有則直接新增現在的點。

checkForNewHit方法

/**
     * 檢查是否滑動到點上
     */
    private Dot checkForNewHit(float x, float y) {
        //判斷y座標是否在點上
        final int rowHit = getRowHit(y);
        if (rowHit < 0) {
            return null;
        }
        //判斷x座標是否在點上
        final int columnHit = getColumnHit(x);
        if (columnHit < 0) {
            return null;
        }

        /**
         * 如果已經選中,則不再選中
         */
        if (mPatternDrawLookup[rowHit][columnHit]) {
            return null;
        }
        //返回一個點物件
        return Dot.of(rowHit, columnHit);
    }

checkForNewHit方法主要是根據x,y座標判斷是否在一個點上,如果是則返回一個點物件。
getRowHit getColumnHit方法

    /**
     * 根據y座標判斷是否在某一個點的y座標上
     * if (y >= hitTop && y <= hitTop + hitSize)這行給點加了一個範圍,在此範圍內都算點上了點
     */
    private int getRowHit(float y) {
        final float squareHeight = mViewHeight;
        float hitSize = squareHeight * mHitFactor;

        float offset = getPaddingTop() + (squareHeight - hitSize) / 2f;
        for (int i = 0; i < sDotCount; i++) {
            float hitTop = offset + squareHeight * i;
            if (y >= hitTop && y <= hitTop + hitSize) {
                return i;
            }
        }
        return -1;
    }

    /**
     * 根據x座標判斷是否在某一個點的x座標上
     * if (x >= hitLeft && x <= hitLeft + hitSize)這行給點加了一個範圍,在此範圍內都算點上了點
     */
    private int getColumnHit(float x) {
        final float squareWidth = mViewWidth;
        float hitSize = squareWidth * mHitFactor;

        float offset = getPaddingLeft() + (squareWidth - hitSize) / 2f;
        for (int i = 0; i < sDotCount; i++) {

            final float hitLeft = offset + squareWidth * i;
            if (x >= hitLeft && x <= hitLeft + hitSize) {
                return i;
            }
        }
        return -1;
    }

這兩個方法是給點加了一個範圍,在此範圍內都算點上了點。

addCellToPattern方法

private void addCellToPattern(Dot newDot) {
        //將選中的點置為true
        mPatternDrawLookup[newDot.mRow][newDot.mColumn] = true;
        //給集合中新增選中的點
        mPattern.add(newDot);
        //開始點放大縮小動畫(隱藏模式用)
        startDotSelectedAnimation(newDot);
        //回撥給使用者選中的點
        notifyPatternProgress();
    }

addCellToPattern方法是將選中的點添到集合中,並把mPatternDrawLookup中點的位置改為true。

以上就是按下 移動 擡起的主要方法,下面再來看下點和線是如何繪製的。

第三步

首先通過onSizeChanged方法來確定patternlockview的大小

onSizeChanged方法

    @Override
    protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
        //設定每一個點佔據的寬度大小
        int adjustedWidth = width - getPaddingLeft() - getPaddingRight();
        mViewWidth = adjustedWidth / (float) sDotCount;
        //設定每一個點佔據的高度度大小
        int adjustedHeight = height - getPaddingTop() - getPaddingBottom();
        mViewHeight = adjustedHeight / (float) sDotCount;
    }

通過onSizeChanged方法,獲取到一個點佔據的寬和高
然後就是onDraw繪製方法了,所有的繪製工作都是由它來完成,同時在滑動過程中,此方法也是在不斷的呼叫。

onDraw方法

    @Override
    protected void onDraw(Canvas canvas) {
        //拿到選中點的集合
        ArrayList<Dot> pattern = mPattern;
        int patternSize = pattern.size();
        //拿到存放點是否選中的二維陣列
        boolean[][] drawLookupTable = mPatternDrawLookup;
        //拿到路徑物件
        Path currentPath = mCurrentPath;
        //清除所有的直線和曲線的路徑,但保持內部資料結構,以便更快地重用。
        currentPath.rewind();

        //判斷是否是隱藏模式
        boolean drawPath = !mInStealthMode;
        if (drawPath) {
            //根據當前模式設定連線線的顏色
            mPathPaint.setColor(getCurrentLineStateColor());
            //是否繪製最後一個點與手指之間的連線
            boolean anyCircles = false;
            float lastX = 0f;
            float lastY = 0f;
            for (int i = 0; i < patternSize; i++) {
                //拿到選中的點
                Dot dot = pattern.get(i);

                //如果點沒有被選中,則不需要跳出迴圈
                if (!drawLookupTable[dot.mRow][dot.mColumn]) {
                    return;
                }
                anyCircles = true;
                //拿到某點的中心座標
                float centerX = getCenterXForColumn(dot.mColumn);
                float centerY = getCenterYForRow(dot.mRow);
                if (i != 0) {
                    DotState state = mDotStates[dot.mRow][dot.mColumn];
                    currentPath.rewind();
                    //當到第二個的時候,則lastX,lastY就是選中的第一個點的中心
                    currentPath.moveTo(lastX, lastY);
                    if (state.mLineEndX != Float.MIN_VALUE
                            && state.mLineEndY != Float.MIN_VALUE) {//主要用於自動繪製
                        currentPath.lineTo(state.mLineEndX, state.mLineEndY);
                    } else {//手動繪製時進入的
                        currentPath.lineTo(centerX, centerY);
                    }
                    //把線連線上
                    canvas.drawPath(currentPath, mPathPaint);
                }
                //當是第一個時,先拿到第一個的中心點,然後從第一個開始畫線,後續再把下一個點的中心點賦值
                lastX = centerX;
                lastY = centerY;
            }

            //這裡繪製最後一個點和和點連線的線
            if (mPatternInProgress && anyCircles) {
                currentPath.rewind();
                currentPath.moveTo(lastX, lastY);
                currentPath.lineTo(mInProgressX, mInProgressY);
                //把線連線上
                canvas.drawPath(currentPath, mPathPaint);
            }
        }

        //迴圈畫點
        for (int i = 0; i < sDotCount; i++) {
            float centerY = getCenterYForRow(i);//排
            for (int j = 0; j < sDotCount; j++) {
                DotState dotState = mDotStates[i][j];
                float centerX = getCenterXForColumn(j);
                float size = dotState.mSize * dotState.mScale;
                float translationY = dotState.mTranslateY;
                drawCircle(canvas, (int) centerX, (int) centerY + translationY,
                        size, drawLookupTable[i][j], dotState.mAlpha);
            }
        }
    }

drawCircle方法

private void drawCircle(Canvas canvas, float centerX, float centerY,
                            float size, boolean partOfPattern, float alpha) {
        //如果隱藏模式則不走
        if (partOfPattern && !isInStealthMode()) {
            //設定點外環的顏色
            mRingPaint.setColor(getCurrentDotStrokeColor(partOfPattern));
            //畫點的外環
            canvas.drawCircle(centerX, centerY, size, mRingPaint);
        }
        //畫點
        mDotPaint.setColor(getCurrentDotStateColor(partOfPattern));
        mDotPaint.setAlpha((int) (alpha * 255));
        canvas.drawCircle(centerX, centerY, size / 2, mDotPaint);
    }

在onDraw方法中對畫什麼顏色的點,什麼顏色的線都做了判斷。
至此整個繪製過程就算完成了,剩下的一些顏色的判斷,各個狀態的回撥,各個模式都比較簡單,就不再這裡特別說明了。

貢獻

這個庫是從Aritra Roy的PatternLockView獲取並添加了一些改進使其更加靈活,如果您發現bug或想改進它的任何方面,可以自由地用拉請求進行貢獻

原始碼下載
APK下載

相關推薦

Android手勢密碼原理分析

在上一篇介紹了手勢密碼的使用,這一篇將主要介紹手勢密碼的原理,手勢密碼的功能主要是由自定義PatternLockView實現的。那咱這就一步一步來揭開PatternLockView的面紗。 效果圖 步驟 第一步 自定義PatternLockV

Android P zygote 原理分析之SystemServer的啟動

SystemServer 在android中的核心服務之一,系統中的大多數服務都執行在這個程序,所以當zygote 啟動後第一個啟動的就是SystemServer ,因為SystemServer 的重要性,如果SystemServer啟動失敗或者中間出現異常導致崩潰,都會引起

Android手勢密碼實現方案

一、大致介面介紹: 圖1 圖2 圖3 圖4 圖1:手勢密碼繪製介面 【主要是繪製上方的9個提示圖示和9個宮格密碼圖示】 圖2:設定手勢密碼 【監聽手勢的輸入,TouchEvent的事件處理,獲取輸入的手勢密碼,同時顯示在上方的提示區域】 圖3

android消除鋸齒原理分析

前言在Android中view繪畫是很重要的一點,當view重寫、surfaceView重寫,都會涉及到如何把一個檢視畫的完美、邊角不在毛躁躁,下面會從原來、業務場景、防鋸齒、防鋸齒實現原理。一、鋸齒的原由:1. 業務場景1.Android 畫圓形檢視如:使用者頭像圓形的。2

Android RecyclerView工作原理分析(上)

基本使用   RecyclerView的基本使用並不複雜,只需要提供一個RecyclerView.Apdater的實現用於處理資料集與ItemView的繫結關係,和一個RecyclerView.LayoutManager的實現用於 測量並佈局 ItemView

Android Watchdog機制原理分析

如我們所知,當應用超過一定時間無響應的時候,系統為了不讓應用長時處於不可操作的狀態,會彈出一個“無響應”(ANR)的對話方塊,使用者可以選擇強制關閉,從而關掉這個程序。 ANR機制是針對應用的,對於系統程序來說,如果長時間“無響應”,Android系統設計

Android-ANR總結原理分析

1、概述 ANR即Application Not Responding(應用程式無響應),一般在ANR的時候會彈出一個應用無響應對話方塊,同時會候產生一個日誌檔案trace.txt,位於/data/anr/資料夾下面,trace檔案是Android Davik

Android手勢密碼

首先宣告一下,九宮格佈局是從網上扒了一個大神寫好的,大家在專案中實現的話可以直接把: Drawl,GuestureLockView,Point類直接複製到自己的專案中; 想了解功能的可以仔細看下原始碼中的這三個類,裡面寫的也非常詳細; 使用GuestureLockVi

Android手勢密碼view筆記(一)

前言:不知不覺已經在這座陌生又熟悉的城市呆了一年多了,說不出什麼感覺,可是即使是自己感覺自己沒什麼變化,但是周圍的事物卻不斷的在變,不知道自己選擇的路未來如何,但是當下我還是會努力、努力、再努力的,加油,騷年!~說了一堆廢話,哈哈~! 好了,下面進入今天的主題

android黑科技系列——修改鎖屏密碼和惡意鎖機樣本原理分析

無需 功能 log 輔助 數據庫文件 手勢密碼 安全網 樣式 進制 一、Android中加密算法 上一篇文章已經介紹了Android中系統鎖屏密碼算法原理,這裏在來總結說一下: 第一種:輸入密碼算法 將輸入的明文密碼+設備的salt值,然後操作MD5和SHA1之後在轉

Android 65K問題之Multidex原理分析及NoClassDefFoundError的解決方法

bottom mini ati ... types auto weight right for Android 65K問題相信困惑了不少人,盡管AS的出來能夠通過分dex高速解決65K問題,可是同一時候也easy由於某些代碼沒有打包到MainDex裏

android黑科技系列——分析某直播App的協議加密原理以及調用加密方法進行協議參數構造

輸出結果 防護 返回 不能 定義類 多個 類型 所在 文件中 一、前言 隨著直播技術火爆之後,各家都出了直播app,早期直播app的各種請求協議的參數信息都沒有做任何加密措施,但是慢慢的有人開始利用這個後門開始弄刷粉關註工具,可以讓一個新生的小花旦分分鐘變成網紅。所以介於

Android XListView實現原理講解及分析

就是 指定 不同 true -h -name 修改 一個 部分 XListview是一個非常受歡迎的下拉刷新控件,但是已經停止維護了。之前寫過一篇XListview的使用介紹,用起來非常簡單,這兩天放假無聊,研究了下XListview的實現原理,學到了很多,今天分享給大家。

Android系統的智能指針(輕量級指針、強指針和弱指針)的實現原理分析【轉】

其中 sin 類的定義 reason ava tab eas file 現在 Android系統的運行時庫層代碼是用C++來編寫的,用C++ 來寫代碼最容易出錯的地方就是指針了,一旦使用不當,輕則造成內存泄漏,重則造成系統崩潰。不過系統為我們提供了智能指針,避免出現上述問題

Android官方架構組件:Lifecycle詳解&迪士尼彩樂園網站架設原理分析

ner 觀察者 and 順序 觸發 組件 oncreate mcr save 我們先將重要的這些類挑選出來: LifecycleObserver接口( Lifecycle觀察者):實現該接口的類,通過註解的方式,可以通過被LifecycleOwner類的addObserve

Android官方架構組件:Lifecycle詳解&迪士尼彩樂園定制開發原理分析

npr save this end ons 關於 直接 能夠 封裝 Lifecycle 是一個類,它持有關於組件(如 Activity 或 Fragment)生命周期狀態的信息,並且允許其他對象觀察此狀態。 我們只需要2步: 1、Prestener繼承LifecycleOb

Android官方架構組件:Lifecycle詳解&迪士尼彩樂園平臺搭建原理分析

基類 客服 androi lifecycle 利用 思想 pub 遇到 原理 在過去的谷歌IO大會上,Google官方向我們推出了 Android Architecture Components,其中談到Android組件處理生命周期的問題,向我們介紹了 Handling

Android系統root破解原理分析

上一篇文章 Android adb 原始碼分析 理論基礎 root破解過程的終極目標是替換掉系統中的su程式。但是要想替換掉系統中su程式本身就是需要root許可權的,怎樣在root破解過程中獲得root許可權,成為我們研究的重點了。下面我們先清點一下我們需要破解系統情況,假設需要破

滴滴開源Android外掛化框架VirtualAPK原理分析

概述 Activity 支援 Hook ActivityManagerService Hook Instrumentation 啟動外掛Acti

Android LayoutInflater原理分析,帶你一步步深入瞭解View

有段時間沒寫部落格了,感覺都有些生疏了呢。最近繁忙的工作終於告一段落,又有時間寫文章了,接下來還會繼續堅持每一週篇的節奏。 有不少朋友跟我反應,都希望我可以寫一篇關於View的文章,講一講View的工作原理以及自定義View的方法。沒錯,承諾過的文章我是一定要兌現的,而且在View這個話題上我還