android 自动更新

APP自动更新,直接用

public class UpdateAPP {
private static  int progress; // 定义进度值
private static String savePath; // APK下载之后保存的地址
private static String saveFileName; // APK的文件名
private static RemoteViews view = null; // 用来设置通知的View
private static NotificationManager nm = null;
private static Notification nn = null; // 引入通知
private static FlikerProgressBar flikerProgressBar;
private static int a;
private static Dialog DownLoad;
private static int handmsg = 1;
private static final int DOWN_UPDATE = 0;// 下载中消息
private static final int DOWN_OVER = 1;// 下载完成消息
private static String apkDownloadPath; // 应用下载的地址
private static Context mContext;


public static void showUpdateApp(final Context context, final String message, final String url) {
    mContext =context;
    nm = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);//获取系统通知的服务
    nn = new Notification();//创建一个通知对象
    apkDownloadPath =url;
    savePath = Environment.getExternalStorageDirectory()
            + "/csnw/";  //自定义下载文件保存地址
    saveFileName = savePath + "csnw.apk"; //自定义文件名


    //可根据需求加入自己设计的dialog
    AlertDialog dialog = new AlertDialog.Builder(context)
            .setTitle("版本更新")
            .setMessage(message)
            .setCancelable(false)
            .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {

                }
            }).setPositiveButton("确定", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    File apkfile = new File(saveFileName);
                    if(apkfile.exists()){
                        apkfile.delete();
                    }
                    a = 0;
                    view = new RemoteViews(context.getPackageName(), R.layout.download_progress_state_view);
                    nn.icon = R.mipmap.ic_launcher;
                    showDownLoad(context);
                    new Thread(mdownApkRunnable).start();

                }
            }).create();

    dialog.setCanceledOnTouchOutside(false);
    dialog.show();
}

public static void showDownLoad(Context context) {
    LayoutInflater inflater = (LayoutInflater) context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    DownLoad = new Dialog(context,R.style.dialog);

    View layout = inflater.inflate(R.layout.dialog_download, null);
    DownLoad.requestWindowFeature(Window.FEATURE_NO_TITLE);
    DownLoad.addContentView(layout, new ViewGroup.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
    flikerProgressBar = (FlikerProgressBar) layout.findViewById(R.id.flikerbar);
    flikerProgressBar.setProgress(handmsg);

    LinearLayout ll_btn_cancel =layout.findViewById(R.id.ll_btn_cancel);
    ll_btn_cancel.setVisibility(View.GONE);

    Button btn_cancel = (Button) layout.findViewById(R.id.btn_cancel);
    btn_cancel.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            a = 1;
            DownLoad.dismiss();
        }
    });
    DownLoad.show();
    if(flikerProgressBar.getProgressText().equals("下载完成")){
        a = 1;
        DownLoad.dismiss();
    }
}

// 下载APK的线程匿名类START
public static  Runnable mdownApkRunnable = new Runnable() {
    @Override
    public void run() {
        try {
            URL url = new URL(apkDownloadPath);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.connect();
            int length = conn.getContentLength();
            InputStream is = conn.getInputStream();

            File file = new File(savePath);
            if (!file.exists()) {
                file.mkdir();
            }
            String apkFile = saveFileName;
            File ApkFile = new File(apkFile);
            FileOutputStream fos = new FileOutputStream(ApkFile);

            int count = 0;
            byte buf[] = new byte[1024];
            do {
                int numread = is.read(buf);
                count += numread;
                progress = (int) (((float) count / length) * 100);

                if(handmsg < progress){
                    handmsg ++;
                    mHandler.sendEmptyMessage(DOWN_UPDATE);
                }

                if(a == 1){
                    fos.close();
                    is.close();
                    break;
                }
                // 更新进度
                if (numread <= 0) {
                    // 下载完成通知安装
                    mHandler.sendEmptyMessage(DOWN_OVER);
                    break;
                }
                fos.write(buf, 0, numread);
            } while (true || a == 1);// 点击取消就停止下载.
            fos.close();
            is.close();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
};
// 下载APK的线程匿名类END

// 处理下载进度的Handler Start
public static Handler mHandler = new Handler() {
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case DOWN_UPDATE:
                flikerProgressBar.setProgress(handmsg);
                view.setProgressBar(R.id.download_progressbar, 100, handmsg,false);
                view.setTextViewText(R.id.download_progress_text, handmsg + "%");
                nn.contentView = view;
                nn.flags = Notification.FLAG_AUTO_CANCEL;
                nm.notify(0, nn);
                super.handleMessage(msg);
                break;
            case DOWN_OVER:
                nm.cancel(0);
                flikerProgressBar.finishLoad();
                DownLoad.dismiss();
                App.showToast("下载完成");

                installApk();
                break;
            default:
                break;
        }
    };
};

// 安装apk
public static void installApk() {
    File apkfile = new File(saveFileName);
    if (!apkfile.exists()) {
        App.showToast( "安装文件不存在,请检查");
        return;
    }

  //项目的包名 自己改
    if(Build.VERSION.SDK_INT>=24){
        Uri apkUri = FileProvider.getUriForFile(mContext, "项目的包名"+".fileprovider", apkfile);//在AndroidManifest中的android:authorities值
        Intent install = new Intent(Intent.ACTION_VIEW);
        install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//添加这一句表示对目标应用临时授权该Uri所代表的文件
        install.setDataAndType(apkUri, "application/vnd.android.package-archive");
        mContext.startActivity(install);
    }else{
        Intent i = new Intent(Intent.ACTION_VIEW);
        i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        i.setAction(android.content.Intent.ACTION_VIEW);
        i.setDataAndType(Uri.fromFile(apkfile),
                "application/vnd.android.package-archive");
        mContext.startActivity(i);
    }

}



/**
 * 浏览器下载apk
 * @param apkDownloadPath
 */
public static void downloadByBrowser(String apkDownloadPath){
    Uri uri  = Uri.parse(apkDownloadPath);
    Intent intent = new Intent(Intent.ACTION_VIEW,uri);
    mContext.startActivity(intent);

}

}

download_progress_state_view

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingRight="15dp"
android:orientation="horizontal" >
<!-- 通知栏里通知的图标(也就是应用的图标) -->
<ImageView
    android:id="@+id/download_progress_img"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@mipmap/ic_launcher"/>

<!-- 通知栏里的下载进度条 -->
<ProgressBar
    android:id="@+id/download_progressbar"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="200dp"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:layout_marginLeft="15dp"/>

<!-- 下载进度百分比 -->
<TextView
    android:id="@+id/download_progress_text"
    android:layout_width="0dp"
    android:layout_weight="1"
    android:layout_height="wrap_content"
    android:layout_marginLeft="15dp"
    android:paddingRight="15dp"
    />
</LinearLayout>

dialog_download

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@color/white"
android:orientation="vertical">

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:orientation="vertical" >


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="vertical" >

        <FlikerProgressBar
            app:radius="10sp"
            android:layout_marginLeft="5dp"
            android:layout_marginRight="5dp"
            android:layout_marginTop="20dp"
            android:layout_marginBottom="20dp"
            android:id="@+id/flikerbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:loadingColor="#40C4FF"
            app:stopColor="#FF9800"
            app:textSizeProgressBar="12sp" />
    </LinearLayout>

    <View
        android:layout_width="fill_parent"
        android:layout_height="1.0px"
        android:layout_marginLeft="1.0px"
        android:layout_marginRight="1.0px"
        android:layout_marginTop="0sp"
        android:background="#bbbbbb" />

    <LinearLayout
        android:id="@+id/ll_btn_cancel"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="0sp"
        android:background="#dddddd"
        android:gravity="center"
        android:paddingTop="10dp"
        android:paddingBottom="10dp"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/btn_cancel"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="5sp"
            android:layout_marginLeft="10sp"
            android:layout_marginRight="10sp"
            android:layout_marginTop="5sp"
            android:layout_weight="1"
            android:background="@drawable/bg_green_8dp_bottom"
            android:text="取消"
            android:textColor="#ffffff"
            android:textSize="20sp" />


    </LinearLayout>
</LinearLayout>

</RelativeLayout>

R.style.dialog

 <style name="dialog" parent="@android:style/Theme.Dialog">
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowFrame">@null</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:windowIsFloating">true</item>
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:windowCloseOnTouchOutside">false</item>
    <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
    <item name="android:backgroundDimEnabled">false</item>
    <item name="android:background">#00000000</item>
</style>

FlikerProgressBar

public class FlikerProgressBar extends View implements Runnable {
private PorterDuffXfermode xfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP);

private int DEFAULT_HEIGHT_DP = 35;

private int borderWidth;

private float maxProgress = 100f;

private Paint textPaint;

private Paint bgPaint;

private Paint pgPaint;

private String progressText;

private Rect textRect;

private RectF bgRectf;

/**
 * 左右来回移动的滑块
 */
private Bitmap flikerBitmap;

/**
 * 滑块移动最左边位置,作用是控制移动
 */
private float flickerLeft;

/**
 * 进度条 bitmap ,包含滑块
 */
private Bitmap pgBitmap;

private Canvas pgCanvas;

/**
 * 当前进度
 */
private float progress;

private boolean isFinish;

private boolean isStop;

/**
 * 下载中颜色
 */
private int loadingColor;

/**
 * 暂停时颜色
 */
private int stopColor;

/**
 * 进度文本、边框、进度条颜色
 */
private int progressColor;

private int textSize;

private int radius;

private Thread thread;

BitmapShader bitmapShader;

public FlikerProgressBar(Context context) {
    this(context, null, 0);
}

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

public FlikerProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    initAttrs(attrs);
}

private void initAttrs(AttributeSet attrs) {
    TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.FlikerProgressBar);
    try {
        textSize = (int) ta.getDimension(R.styleable.FlikerProgressBar_textSizeProgressBar, 12);
        loadingColor = ta.getColor(R.styleable.FlikerProgressBar_loadingColor, Color.parseColor("#40c4ff"));
        stopColor = ta.getColor(R.styleable.FlikerProgressBar_stopColor, Color.parseColor("#ff9800"));
        radius = (int) ta.getDimension(R.styleable.FlikerProgressBar_radius, 0);
        borderWidth = (int) ta.getDimension(R.styleable.FlikerProgressBar_borderWidth, 1);
    } finally {
        ta.recycle();
    }
}

private void init() {
    bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
    bgPaint.setStyle(Paint.Style.STROKE);
    bgPaint.setStrokeWidth(borderWidth);

    pgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    pgPaint.setStyle(Paint.Style.FILL);

    textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    textPaint.setTextSize(textSize);

    textRect = new Rect();
    bgRectf = new RectF(borderWidth, borderWidth, getMeasuredWidth() - borderWidth, getMeasuredHeight() - borderWidth);

    if (isStop) {
        progressColor = stopColor;
    } else {
        progressColor = loadingColor;
    }

    flikerBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.flicker);
    flickerLeft = -flikerBitmap.getWidth();

    initPgBimap();
}

private void initPgBimap() {
    pgBitmap = Bitmap.createBitmap(getMeasuredWidth() - borderWidth, getMeasuredHeight() - borderWidth, Bitmap.Config.ARGB_8888);
    pgCanvas = new Canvas(pgBitmap);
    thread = new Thread(this);
    thread.start();
}


@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
    int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
    int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
    int height = 0;
    switch (heightSpecMode) {
        case MeasureSpec.AT_MOST:
            height = dp2px(DEFAULT_HEIGHT_DP);
            break;
        case MeasureSpec.EXACTLY:
        case MeasureSpec.UNSPECIFIED:
            height = heightSpecSize;
            break;
    }
    setMeasuredDimension(widthSpecSize, height);

    if (pgBitmap == null) {
        init();
    }

}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    //背景
    drawBackGround(canvas);

    //进度
    drawProgress(canvas);

    //进度text
    drawProgressText(canvas);

    //变色处理
    drawColorProgressText(canvas);
}

/**
 * 边框
 *
 * @param canvas
 */
private void drawBackGround(Canvas canvas) {
    bgPaint.setColor(progressColor);
    //left、top、right、bottom不要贴着控件边,否则border只有一半绘制在控件内,导致圆角处线条显粗
    canvas.drawRoundRect(bgRectf, radius, radius, bgPaint);
}

/**
 * 进度
 */
private void drawProgress(Canvas canvas) {
    pgPaint.setColor(progressColor);

    float right = (progress / maxProgress) * getMeasuredWidth();
    pgCanvas.save();
    pgCanvas.clipRect(0, 0, right, getMeasuredHeight());
    pgCanvas.drawColor(progressColor);
    pgCanvas.restore();

    if (!isStop) {
        pgPaint.setXfermode(xfermode);
        pgCanvas.drawBitmap(flikerBitmap, flickerLeft, 0, pgPaint);
        pgPaint.setXfermode(null);
    }

    //控制显示区域
    bitmapShader = new BitmapShader(pgBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
    pgPaint.setShader(bitmapShader);
    canvas.drawRoundRect(bgRectf, radius, radius, pgPaint);
}

/**
 * 进度提示文本
 *
 * @param canvas
 */
private void drawProgressText(Canvas canvas) {
    textPaint.setColor(progressColor);
    progressText = getProgressText();
    textPaint.getTextBounds(progressText, 0, progressText.length(), textRect);
    int tWidth = textRect.width();
    int tHeight = textRect.height();
    float xCoordinate = (getMeasuredWidth() - tWidth) / 2;
    float yCoordinate = (getMeasuredHeight() + tHeight) / 2;
    canvas.drawText(progressText, xCoordinate, yCoordinate, textPaint);
}

/**
 * 变色处理
 *
 * @param canvas
 */
private void drawColorProgressText(Canvas canvas) {
    textPaint.setColor(Color.WHITE);
    int tWidth = textRect.width();
    int tHeight = textRect.height();
    float xCoordinate = (getMeasuredWidth() - tWidth) / 2;
    float yCoordinate = (getMeasuredHeight() + tHeight) / 2;
    float progressWidth = (progress / maxProgress) * getMeasuredWidth();
    if (progressWidth > xCoordinate) {
        canvas.save();
        float right = Math.min(progressWidth, xCoordinate + tWidth * 1.1f);
        canvas.clipRect(xCoordinate, 0, right, getMeasuredHeight());
        canvas.drawText(progressText, xCoordinate, yCoordinate, textPaint);
        canvas.restore();
    }
}

public void setProgress(float progress) {
    if (!isStop) {
        if (progress < maxProgress) {
            this.progress = progress;
        } else {
            this.progress = maxProgress;
            finishLoad();
        }
        invalidate();
    }
}

public void setStop(boolean stop) {
    isStop = stop;
    if (isStop) {
        progressColor = stopColor;
        thread.interrupt();
    } else {
        progressColor = loadingColor;
        thread = new Thread(this);
        thread.start();
    }
    invalidate();
}

public void finishLoad() {
    isFinish = true;
    setStop(true);
}

public void toggle() {
    if (!isFinish) {
        if (isStop) {
            setStop(false);
        } else {
            setStop(true);
        }
    }
}

@Override
public void run() {
    int width = flikerBitmap.getWidth();
    try {
        while (!isStop && !thread.isInterrupted()) {
            flickerLeft += dp2px(5);
            float progressWidth = (progress / maxProgress) * getMeasuredWidth();
            if (flickerLeft >= progressWidth) {
                flickerLeft = -width;
            }
            postInvalidate();
            Thread.sleep(20);
        }
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

/**
 * 重置
 */
public void reset() {
    setStop(true);
    progress = 0;
    isFinish = false;
    isStop = false;
    progressColor = loadingColor;
    progressText = "";
    flickerLeft = -flikerBitmap.getWidth();
    initPgBimap();
}

public float getProgress() {
    return progress;
}

public boolean isStop() {
    return isStop;
}

public boolean isFinish() {
    return isFinish;
}

public String getProgressText() {
    String text = "";
    if (!isFinish) {
        if (!isStop) {
            text = "下载中" + progress + "%";
        } else {
            text = "继续";
        }
    } else {
        text = "下载完成";
    }

    return text;
}

private int dp2px(int dp) {
    float density = getContext().getResources().getDisplayMetrics().density;
    return (int) (dp * density);
}
}
FlikerProgressBar.png
flicker.png
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容