Android 功能集锦(2017.7)

1.自动安装/卸载APK,静默安装/卸载APK。

import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.util.Log;

import java.io.File;
import java.io.PrintWriter;

/**
 * @author Created by qlang on 2017/6/27.
 */
public class ApkUtils {
    /**
     * 安装APK
     *
     * @param apkPath
     * @param context
     * @return
     */
    public static boolean install(Context context, String apkPath) {
        // 先判断手机是否有root权限
        if (hasRootPerssion()) {
            // 有root权限,利用静默安装实现
            return silentInstall(apkPath);
        } else {
            // 没有root权限,利用意图进行安装
            File file = new File(apkPath);
            if (!file.exists())
                return false;
            Intent intent = new Intent();
            intent.setAction("android.intent.action.VIEW");
            intent.addCategory("android.intent.category.DEFAULT");
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
            context.startActivity(intent);
            return true;
        }
    }

    /**
     * 卸载APK
     *
     * @param packageName
     * @param context
     * @return
     */
    public static boolean uninstall(Context context, String packageName) {
        if (hasRootPerssion()) {
            // 有root权限,利用静默卸载实现
            return silentUninstall(packageName);
        } else {
            Uri packageURI = Uri.parse("package:" + packageName);
            Intent uninstallIntent = new Intent(Intent.ACTION_DELETE, packageURI);
            uninstallIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(uninstallIntent);
            return true;
        }
    }

    /**
     * 判断手机是否有root权限
     *
     * @return
     */
    private static boolean hasRootPerssion() {
        PrintWriter PrintWriter = null;
        Process process = null;
        try {
            process = Runtime.getRuntime().exec("su");
            PrintWriter = new PrintWriter(process.getOutputStream());
            PrintWriter.flush();
            PrintWriter.close();
            int value = process.waitFor();
            return returnResult(value);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (process != null) {
                process.destroy();
            }
        }
        return false;
    }

    /**
     * 静默安装
     *
     * @param apkPath
     * @return
     */
    private static boolean silentInstall(String apkPath) {
        PrintWriter PrintWriter = null;
        Process process = null;
        try {
            process = Runtime.getRuntime().exec("su");
            PrintWriter = new PrintWriter(process.getOutputStream());
            String s = apkPath.substring(0, apkPath.lastIndexOf("/") + 1);
            PrintWriter.println("chmod 777 " + s);
//            PrintWriter.println("export LD_LIBRARY_PATH=/vendor/lib:/system/lib");
            PrintWriter.println("pm install -r " + apkPath);
//            PrintWriter.println("exit");
            PrintWriter.flush();
            PrintWriter.close();
            int value = process.waitFor();
//            Log.e("QL", s + " " + value);
            return returnResult(value);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (process != null) {
                process.destroy();
            }
        }
        return false;
    }

    /**
     * 静默卸载
     *
     * @param packageName
     * @return
     */
    private static boolean silentUninstall(String packageName) {
        PrintWriter PrintWriter = null;
        Process process = null;
        try {
            process = Runtime.getRuntime().exec("su");
            PrintWriter = new PrintWriter(process.getOutputStream());
            PrintWriter.println("LD_LIBRARY_PATH=/vendor/lib:/system/lib ");
            PrintWriter.println("pm uninstall " + packageName);
            PrintWriter.flush();
            PrintWriter.close();
            int value = process.waitFor();
            return returnResult(value);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (process != null) {
                process.destroy();
            }
        }
        return false;
    }

    /**
     * 启动app
     * com.exmaple.client/.MainActivity
     * com.exmaple.client/com.exmaple.client.MainActivity
     *
     * @param packageName
     * @param activityName
     * @return
     */
    public static boolean startApp(String packageName, String activityName) {
        boolean isSuccess = false;
        String cmd = "am start -n " + packageName + "/" + activityName + " \n";
        Process process = null;
        try {
            process = Runtime.getRuntime().exec(cmd);
            int value = process.waitFor();
            return returnResult(value);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (process != null) {
                process.destroy();
            }
        }
        return isSuccess;
    }


    private static boolean returnResult(int value) {
        // 代表成功
        if (value == 0) {
            return true;
        } else if (value == 1) { // 失败
            return false;
        } else { // 未知情况
            return false;
        }
    }
}


简单的视频播放器,通过接收bitmap来进行播放,不涉及解码等,自带放大功能(未完善)、手势接口等

VideoDisplayView.java

package com.nextstage.faceverify.view;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.PointF;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

/**
 * the video display view
 *
 * @author Created by QinLang on 2017/4/28.
 */
public class VideoDisplayView extends SurfaceView implements SurfaceHolder.Callback, Runnable, GestureDetector.OnGestureListener, VideoListener {
    private final String TAG = this.getClass().getSimpleName();

    private static final float DEFAULT_MAX_ZOOM_SCALE = 2.0f;
    private static final int MAIN_THREAD_FREQUENCY = 30;//main thread frequency. units(ms)
    private static final int FLING_MIN_DISTANCE = 100;
    private static final int FLING_MIN_VELOCITY = 0;

    private SurfaceHolder surfaceHolder;
    private Thread mainThread;
    private boolean isThreadRunning = false;

    private GestureDetector mGestureDetector;

    private Canvas canvas = new Canvas();
    private Rect mRectCanvas = new Rect(); // used for render image.
    private Rect mRectMonitor = new Rect(); // used for store size of monitor.

    private int mCurVideoWidth = 0;
    private int mCurVideoHeight = 0;

    private int vLeft, vTop, vRight, vBottom;

    private float mCurrentMaxScale = DEFAULT_MAX_ZOOM_SCALE;
    private float mCurrentScale = 1.0f;

    private PointF mStartPoint = new PointF();
    private PointF mMidPoint = new PointF();
    private PointF mMidPointForCanvas = new PointF();
    private float mOrigDist = 0f;
    private long mLastZoomTime;

    private static final int NONE = 0;
    private static final int DRAG = 1;
    private static final int ZOOM = 2;
    private int mPinchedMode = NONE;
    private static final int TOUCH_DOWN = 0;
    private static final int TOUCH_MOVE = 1;
    private static final int TOUCH_UP = 2;
    private static final int TOUCH_CANCLE = 3;
    private int touchState = -1;

    private volatile Bitmap mLastFrame;

    private ViewTouchListener viewTouchListener;
    private ViewListener viewListener;
    private GestureListener gestureListener;

    private boolean isMoveing = false;

    /**
     * view touch listener
     */
    public interface ViewTouchListener {
        /**
         * touch callback
         *
         * @param event
         */
        void onTouch(MotionEvent event);
    }

    /**
     * The video SurfaceView life change
     */
    public interface ViewListener {
        /**
         * The view created
         */
        void onCreated();

        /**
         * The view destroyed
         */
        void onDestroyed();
    }

    /**
     * The gesture direction
     */
    public interface GestureListener {
        void flingLeft();

        void flingRight();

        void flingUp();

        void flingDown();
    }

    public VideoDisplayView(Context context) {
        this(context, null);
    }

    public VideoDisplayView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public VideoDisplayView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        surfaceHolder = getHolder();
        surfaceHolder.addCallback(this);

        surfaceHolder.setFormat(PixelFormat.TRANSPARENT);
        //surfceview放置在顶层,即始终位于最上层
        setZOrderOnTop(true);

        mGestureDetector = new GestureDetector(this);
        this.setLongClickable(true);
    }

    /**
     * set this view on touched listener
     *
     * @param listener
     */
    public void setViewTouchListener(ViewTouchListener listener) {
        this.viewTouchListener = listener;
    }

    /**
     * set view life change callback
     *
     * @param listener
     */
    public void setViewListener(ViewListener listener) {
        this.viewListener = listener;
    }

    /**
     * set the view touch gesture listener
     *
     * @param listener
     */
    public void setGestureListener(GestureListener listener) {
        this.gestureListener = listener;
    }

    /**
     * set preview view can max zoom level
     *
     * @param value
     */
    public void setMaxZoom(float value) {
        mCurrentMaxScale = value;
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        if (viewListener != null) {
            viewListener.onCreated();
        }
    }

    /**
     * start video preview thread
     */
    public void startPreview() {
        if (mainThread == null) {
            mainThread = new Thread(this);
            if (!mainThread.isAlive()) {
                mainThread.start();
            }
        }
    }

    /**
     * stop video preview thread and init
     */
    public void stopPreview() {
        isThreadRunning = false;
        if (mainThread != null && mainThread.isAlive()) {
            try {
                mainThread.stop();
                mainThread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
            mainThread = null;
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        synchronized (this) {
            mRectMonitor.set(0, 0, width, height);
            mRectCanvas.set(0, 0, width, height);

            if (mCurVideoWidth == 0 || mCurVideoHeight == 0) {
                if (height < width) { // landscape layout
                    mRectCanvas.right = 4 * height / 3;
                    mRectCanvas.offset((width - mRectCanvas.right) / 2, 0);
                } else { // portrait layout
                    mRectCanvas.bottom = 3 * width / 4;
                    mRectCanvas.offset(0, (height - mRectCanvas.bottom) / 2);
                }
            } else {
                if ((mRectMonitor.bottom - mRectMonitor.top) < (mRectMonitor.right - mRectMonitor.left)) { // landscape layout
                    double ratio = (double) mCurVideoWidth / mCurVideoHeight;
                    mRectCanvas.right = (int) (mRectMonitor.bottom * ratio);
                    mRectCanvas.offset((mRectMonitor.right - mRectCanvas.right) / 2, 0);
                } else { // portrait layout
                    double ratio = (double) mCurVideoWidth / mCurVideoHeight;
                    mRectCanvas.bottom = (int) (mRectMonitor.right / ratio);
                    mRectCanvas.offset(0, (mRectMonitor.bottom - mRectCanvas.bottom) / 2);
                }
            }

            vLeft = mRectCanvas.left;
            vTop = mRectCanvas.top;
            vRight = mRectCanvas.right;
            vBottom = mRectCanvas.bottom;

            mCurrentScale = 1.0f;

            parseMidPoint(mMidPoint, vLeft, vTop, vRight, vBottom);
            parseMidPoint(mMidPointForCanvas, vLeft, vTop, vRight, vBottom);
        }
    }

    private void parseMidPoint(PointF point, float left, float top, float right, float bottom) {
        point.set((left + right) / 2, (top + bottom) / 2);
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        if (viewListener != null) {
            viewListener.onDestroyed();
        }
        isThreadRunning = false;
    }

    @Override
    public void run() {
        isThreadRunning = true;
        while (isThreadRunning) {
            long start = System.currentTimeMillis();
            myDraw(canvas);
            long end = System.currentTimeMillis();
            try {
                if (end - start < MAIN_THREAD_FREQUENCY) {
                    Thread.sleep(MAIN_THREAD_FREQUENCY - (end - start));
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        isThreadRunning = false;
    }

    //    @Override
    public void myDraw(Canvas canvas) {
        try {
            canvas = surfaceHolder.lockCanvas();
            if (canvas != null) {
                canvas.drawColor(Color.BLACK);
                if (mLastFrame != null && !mLastFrame.isRecycled()) {
//                    Log.e("QL", "drwaBitmap -----> " + String.valueOf(mLastFrame.getByteCount()));
                    canvas.drawBitmap(mLastFrame, null, mRectCanvas, null);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (canvas != null) surfaceHolder.unlockCanvasAndPost(canvas);
            canvas = null;
        }
//        if (null != canvas)
//            super.draw(canvas);
    }

    @Override
    public void recvFrameData(Bitmap bitmap, int width, int height) {
        mLastFrame = bitmap;

        if (bitmap.getWidth() > 0 && bitmap.getHeight() > 0 &&
                (bitmap.getWidth() != mCurVideoWidth || bitmap.getHeight() != mCurVideoHeight)) {

            mCurVideoWidth = bitmap.getWidth();
            mCurVideoHeight = bitmap.getHeight();

            mRectCanvas.set(0, 0, mRectMonitor.right, mRectMonitor.bottom);

            if ((mRectMonitor.bottom - mRectMonitor.top) < (mRectMonitor.right - mRectMonitor.left)) { // landscape layout
                double ratio = (double) mCurVideoWidth / mCurVideoHeight;
                mRectCanvas.right = (int) (mRectMonitor.bottom * ratio);
                mRectCanvas.offset((mRectMonitor.right - mRectCanvas.right) / 2, 0);
            } else { // portrait layout
                double ratio = (double) mCurVideoWidth / mCurVideoHeight;
                mRectCanvas.bottom = (int) (mRectMonitor.right / ratio);
                mRectCanvas.offset(0, (mRectMonitor.bottom - mRectCanvas.bottom) / 2);
            }

            vLeft = mRectCanvas.left;
            vTop = mRectCanvas.top;
            vRight = mRectCanvas.right;
            vBottom = mRectCanvas.bottom;

            mCurrentScale = 1.0f;

            parseMidPoint(mMidPoint, vLeft, vTop, vRight, vBottom);
            parseMidPoint(mMidPointForCanvas, vLeft, vTop, vRight, vBottom);
        }
    }

    @Override
    public boolean onDown(MotionEvent e) {
        return false;
    }

    @Override
    public void onShowPress(MotionEvent e) {

    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        return false;
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        return true;
    }

    @Override
    public void onLongPress(MotionEvent e) {

    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        if (mRectCanvas.left != vLeft || mRectCanvas.top != vTop || mRectCanvas.right != vRight || mRectCanvas.bottom != vBottom)
            return false;

        isMoveing = true;
        if (e1.getX() - e2.getX() > FLING_MIN_DISTANCE && Math.abs(velocityX) > FLING_MIN_VELOCITY) {
            // Fling left
            if (gestureListener != null) {
                gestureListener.flingLeft();
            }
        } else if (e2.getX() - e1.getX() > FLING_MIN_DISTANCE && Math.abs(velocityX) > FLING_MIN_VELOCITY) {
            // Fling right
            if (gestureListener != null) {
                gestureListener.flingRight();
            }
        } else if (e1.getY() - e2.getY() > FLING_MIN_DISTANCE && Math.abs(velocityY) > FLING_MIN_VELOCITY) {
            // Fling down
            if (gestureListener != null) {
                gestureListener.flingDown();
            }
        } else if (e2.getY() - e1.getY() > FLING_MIN_DISTANCE && Math.abs(velocityY) > FLING_MIN_VELOCITY) {
            // Fling up
            if (gestureListener != null) {
                gestureListener.flingUp();
            }
        }
        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mGestureDetector.onTouchEvent(event);

        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                if (mRectCanvas.left != vLeft || mRectCanvas.top != vTop || mRectCanvas.right != vRight || mRectCanvas.bottom != vBottom) {
                    mPinchedMode = DRAG;
                    mStartPoint.set(event.getX(), event.getY());
                }
                touchState = TOUCH_DOWN;
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                float dist = spacing(event);

                if (dist > 10f) {
                    mPinchedMode = ZOOM;
                    mOrigDist = dist;
                    System.out.println("Action_Pointer_Down -> origDist(" + mOrigDist + ")");
                }
                touchState = TOUCH_DOWN;
                break;
            case MotionEvent.ACTION_MOVE:
                isMoveing = true;
                touchState = TOUCH_MOVE;
                if (mPinchedMode == DRAG) {
                    if (System.currentTimeMillis() - mLastZoomTime < 33)
                        return true;

                    PointF currentPoint = new PointF();
                    currentPoint.set(event.getX(), event.getY());

                    int offsetX = (int) currentPoint.x - (int) mStartPoint.x;
                    int offsetY = (int) currentPoint.y - (int) mStartPoint.y;

                    mStartPoint = currentPoint;

                    Rect rect = new Rect();
                    rect.set(mRectCanvas);
                    rect.offset(offsetX, offsetY);

                    int width = rect.right - rect.left;
                    int height = rect.bottom - rect.top;

                    if ((mRectMonitor.bottom - mRectMonitor.top) > (mRectMonitor.right - mRectMonitor.left)) {

                        if (rect.left > mRectMonitor.left) {
                            rect.left = mRectMonitor.left;
                            rect.right = rect.left + width;
                        }

                        if (rect.top > mRectMonitor.top) {
                            rect.top = mRectCanvas.top;
                            rect.bottom = rect.top + height;
                        }

                        if (rect.right < mRectMonitor.right) {
                            rect.right = mRectMonitor.right;
                            rect.left = rect.right - width;
                        }

                        if (rect.bottom < mRectMonitor.bottom) {
                            rect.bottom = mRectCanvas.bottom;
                            rect.top = rect.bottom - height;
                        }
                    } else {
                        if (rect.left > mRectMonitor.left) {
                            rect.left = mRectCanvas.left;
                            rect.right = rect.left + width;
                        }

                        if (rect.top > mRectMonitor.top) {
                            rect.top = mRectMonitor.top;
                            rect.bottom = rect.top + height;
                        }

                        if (rect.right < mRectMonitor.right) {
                            rect.right = mRectCanvas.right;
                            rect.left = rect.right - width;
                        }

                        if (rect.bottom < mRectMonitor.bottom) {
                            rect.bottom = mRectMonitor.bottom;
                            rect.top = rect.bottom - height;
                        }
                    }

                    mRectCanvas.set(rect);
                } else if (mPinchedMode == ZOOM) {
                    if (System.currentTimeMillis() - mLastZoomTime < 33)
                        return true;

                    if (event.getPointerCount() == 1)
                        return true;

                    float newDist = spacing(event);
                    float scale = newDist / mOrigDist;
                    mCurrentScale *= scale;

                    mOrigDist = newDist;

                    if (mCurrentScale > mCurrentMaxScale) {
                        mCurrentScale = mCurrentMaxScale;
                        return true;
                    }

                    if (mCurrentScale < 1.0f) {
                        mCurrentScale = 1.0f;
                    }

                    int maxWidth = (vRight - vLeft) * 3;
                    int maxHeight = (vBottom - vTop) * 3;

                    int scaledWidth = (int) ((float) (vRight - vLeft) * mCurrentScale);
                    int scaledHeight = (int) ((float) (vBottom - vTop) * mCurrentScale);
                    int origWidth = vRight - vLeft;
                    int origHeight = vBottom - vTop;

                    int l = (int) ((mRectMonitor.width() / 2) - (((mRectMonitor.width() / 2) - mRectCanvas.left) * scale));
                    int t = (int) ((mRectMonitor.height() / 2) - (((mRectMonitor.height() / 2) - mRectCanvas.top) * scale));
                    int r = l + scaledWidth;
                    int b = t + scaledHeight;

                    if (scaledWidth <= origWidth || scaledHeight <= origHeight) {
                        l = vLeft;
                        t = vTop;
                        r = vRight;
                        b = vBottom;
                    } else if ((scaledWidth >= maxWidth) || (scaledHeight >= maxHeight)) {
                        l = mRectCanvas.left;
                        t = mRectCanvas.top;
                        r = l + maxWidth;
                        b = t + maxHeight;
                    }

                    mRectCanvas.set(l, t, r, b);

                    mLastZoomTime = System.currentTimeMillis();
                }

                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_POINTER_UP:
                touchState = TOUCH_UP;
                if (mCurrentScale == 1.0f) {
                    mPinchedMode = NONE;
                }
                break;
        }
        if (null != viewTouchListener && touchState == TOUCH_UP && !isMoveing) {
            viewTouchListener.onTouch(event);
            isMoveing = false;
        }
        isMoveing = false;
        return true;
    }

    @SuppressLint("FloatMath")
    private float spacing(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return (float) Math.sqrt(x * x + y * y);
    }
}

接口VideoListener.java

package com.nextstage.faceverify.view;

import android.graphics.Bitmap;

/**
 * The video callBack
 *
 * @author Created by QL on 2017/4/28.
 */
public interface VideoListener {
    /**
     * recv video frame data from video controller
     *
     * @param bitmap bitmap
     * @param width  video width
     * @param height video height
     */
    void recvFrameData(Bitmap bitmap, int width, int height);
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值