登陆时splash初始页调用接口检查app版本。如有更新,使用okGo的文件下载,保存到指定位置,调用Android安装apk。

<!-- Android 8.0 (Android O)为了针对一些流氓软件引导用户安装其他无关应用。在应用权限设置的“特殊访问权限”中,加入了“安装其他应用”的设置 -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
package com.test.activity.sys;

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AlertDialog;
import android.text.format.Formatter;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.TextView;
import android.widget.Toast; import com.lzy.okgo.OkGo;
import com.lzy.okgo.callback.FileCallback;
import com.lzy.okgo.callback.StringCallback;
import com.lzy.okgo.convert.FileConvert;
import com.lzy.okgo.model.Progress;
import com.lzy.okgo.model.Response;
import com.test.BuildConfig;
import com.test.Constant;
import com.test.R;
import com.test.activity.MainActivity;
import com.test.activity.sys.LoginActivity;
import com.test.util.DataUtils; import com.test.view.NumberProgressBar; import org.json.JSONException;
import org.json.JSONObject; import java.io.File;
import java.text.NumberFormat; /**
* @author cralor
* @date 2018/8/8
* 启动页 Activity
*/
public class SplashActivity extends Activity{ public static final int INSTALL_APK_REQUESTCODE = 3;
public static final int GET_UNKNOWN_APP_SOURCES = 7;
private File apkFile;
/**
* 可以额外指定文件的下载目录和下载完成后的文件名
*/
private String destFileDir = Environment.getExternalStorageDirectory() + FileConvert.DM_TARGET_FOLDER + "myAppDownload" + File.separator; private String destFileName = "myApp.apk"; private Handler handler;
private Context content;
private TextView tvDownloadSize;
private TextView tvProgress;
private TextView tvNetSpeed;
private NumberProgressBar pbProgress; private NumberFormat numberFormat;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
//去掉标题栏
requestWindowFeature(Window.FEATURE_NO_TITLE);
// getWindow().setFlags(WindowManager.LayoutParams. FLAG_FULLSCREEN ,WindowManager.LayoutParams. FLAG_FULLSCREEN);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
content = this;
handler = new Handler(Looper.getMainLooper()); numberFormat = NumberFormat.getPercentInstance();
numberFormat.setMinimumFractionDigits(2);
initView();
} /**
* 打开程序时判断是否已经登陆过,且token有效
*/
private void initView() { // ... handler.postDelayed(new Runnable() {
@Override
public void run() {
OkGo.<String>post(Constant.GET_VERSION)
.tag(1)
.execute(new StringCallback() {
@Override
public void onSuccess(Response<String> response) { String data = response.body();
String code = "";
String sysVersion = "";
try {
JSONObject jsonObject = new JSONObject(data);
code = jsonObject.get("code").toString();
sysVersion = jsonObject.get("data").toString();
} catch (JSONException e) {
e.printStackTrace();
}
Log.v("data",""+code);
if(Constant.SUCCESS_CODE.equals(code)){ // Android studio 中 build.gradle 中的版本号
// 获取PackageManager的实例
PackageManager packageManager = getPackageManager();
// getPackageName()是你当前类的包名,0代表是获取版本信息
PackageInfo packInfo = null;
String appVersion = "";
try {
packInfo = packageManager.getPackageInfo(getPackageName(), 0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
if (packInfo != null) {
appVersion = packInfo.versionName;
} if(appVersion.equals(sysVersion)){
Intent intent = new Intent(SplashActivity.this, MainActivity.class);
startActivity(intent);
finish();
}else{
Log.e("SplashActivity","需要更新版本到---"+sysVersion);
Toast.makeText(content, "有新版本需要更新", Toast.LENGTH_SHORT).show();
getVersion();
}
}
}
@Override
public void onError(Response<String> response) {
Toast.makeText(content, "请求失败", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(SplashActivity.this, LoginActivity.class);
startActivity(intent);
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
finish();
}
});
}
}, 3);
} /**
* 更新弹出框
*/
public void getVersion(){
//退出的确认弹出框
new AlertDialog.Builder(content)
.setTitle("提示")
.setMessage("请更新最新版本")
.setCancelable(false)
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int whichButton) {
Toast.makeText(content, "dianjixiazai ", Toast.LENGTH_SHORT).show();
fileDownload();
View view1 = getLayoutInflater().inflate(R.layout.update_app_progress, null); tvDownloadSize = view1.findViewById(R.id.downloadSize);
tvProgress = view1.findViewById(R.id.tvProgress);
tvNetSpeed = view1.findViewById(R.id.netSpeed);
pbProgress = view1.findViewById(R.id.pbProgress); AlertDialog.Builder builder = new AlertDialog.Builder(content);
builder.setTitle("正在下载");
builder.setView(view1);
builder.setCancelable(false);
builder.setNegativeButton("取消", new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
builder.create().show();
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int whichButton) {
finish();
}
})
.show();
} /**
* 获取服务器apk
*/
public void fileDownload() {
//检查是否获得写入权限,未获得则向用户请求。Android 7.0 以上需要动态获取权限
if (ActivityCompat.checkSelfPermission(SplashActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
//未获得,向用户请求
ActivityCompat.requestPermissions(SplashActivity.this, new String[]
{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 200);
}
OkGo.<File>get("https://app地址/app.apk")
.tag(1)
.headers("header1", "headerValue1")
.params("param1", "paramValue1")
/*
* 文件目录如果不指定,默认下载的目录为 sdcard/download/,文件名如果不指定,则按照以下规则命名:
1.首先检查用户是否传入了文件名,如果传入,将以用户传入的文件名命名
2.如果没有传入,那么将会检查服务端返回的响应头是否含有Content-Disposition=attachment;filename=FileName.txt该种形式的响应头,如果有,则按照该响应头中指定的文件名命名文件,如FileName.txt
3.如果上述响应头不存在,则检查下载的文件url,例如:http://image.baidu.com/abc.jpg,那么将会自动以abc.jpg命名文件
4.如果url也把文件名解析不出来,那么最终将以"unknownfile_" + System.currentTimeMillis()命名文件
*/
.execute(new FileCallback(""+destFileDir, ""+destFileName) {
@Override
public void onSuccess(Response<File> response) { String absolutePath = response.body().getAbsolutePath();
apkFile = response.body().getAbsoluteFile();
Log.e("appInstall---", ""+absolutePath); //Android8.0 版本更新无法自动安装问题解决
if (Build.VERSION.SDK_INT >= 26) {
//来判断应用是否有权限安装apk
Log.e("appInstall---", "android版本8.0以上");
boolean installAllowed= getPackageManager().canRequestPackageInstalls();
//有权限
if (installAllowed) {
//安装apk
Log.e("appInstall---", "有权限安装apk");
installApk(apkFile);
} else {
//无权限 申请权限
Log.e("appInstall---", "无权限 申请权限");
ActivityCompat.requestPermissions(SplashActivity.this, new String[]{Manifest.permission.REQUEST_INSTALL_PACKAGES}, INSTALL_APK_REQUESTCODE);
}
} else {
Log.e("appInstall---", "android版本低于8.0");
installApk(apkFile);
}
}
@Override
public void onError(Response<File> response) {
Throwable exception = response.getException();
exception.printStackTrace();
Log.e("eeeee", exception.getMessage());
}
@Override
public void downloadProgress(Progress progress) {
System.out.println(progress);
String downloadLength = Formatter.formatFileSize(getApplicationContext(), progress.currentSize);
String totalLength = Formatter.formatFileSize(getApplicationContext(), progress.totalSize);
tvDownloadSize.setText(downloadLength + "/" + totalLength);
String speed = Formatter.formatFileSize(getApplicationContext(), progress.speed);
tvNetSpeed.setText(String.format("%s/s", speed));
tvProgress.setText(numberFormat.format(progress.fraction));
pbProgress.setMax(10000);
pbProgress.setProgress((int) (progress.fraction * 10000));
}
});
}
/**
* 权限申请回调
* @param requestCode requestCode
* @param permissions permissions
* @param grantResults grantResults
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case INSTALL_APK_REQUESTCODE:
//有注册权限且用户允许安装
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.e("appInstall---", "有注册权限且用户允许安装");
installApk(apkFile);
} else {
//将用户引导至安装未知应用界面。
Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
startActivityForResult(intent, GET_UNKNOWN_APP_SOURCES);
Log.e("appInstall---", "将用户引导至安装未知应用界面");
}
break;
default:break;
}
}
/**
* 将用户引导至安装未知应用界面,允许安装未知应用后,回到当前activity继续安装应用
* @param requestCode requestCode
* @param resultCode resultCode
* @param data data
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.e("appInstall---", "将用户引导至安装未知应用界面,允许安装未知应用后,回到当前activity继续安装应用");
installApk(apkFile);
}
/**
* 安装APK
* @param apkFile apkFile
*/
public void installApk(File apkFile){
//判读版本是否在7.0以上
if(Build.VERSION.SDK_INT >= 24) {
Log.e("appInstall---", "android版本7.");
//在AndroidManifest中的android:authorities的值, BuildConfig.APPLICATION_ID = com.test
Uri apkUri = FileProvider.getUriForFile(content, BuildConfig.APPLICATION_ID+".provider", apkFile);
       Intent install = new Intent(Intent.ACTION_VIEW);
install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
install.setDataAndType(apkUri, "application/vnd.android.package-archive");
startActivity(install);
} else {
Log.e("appInstall---", "android版本低于7.0");
Intent install = new Intent(Intent.ACTION_VIEW);
install.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(install); }
finish();
} /**
* 调用默认浏览器下载apk
*/
public void getApk(){
Uri uri = Uri.parse("https://lighttruck.com.cn:8086/app.apk");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
} }
activity_splash.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
tools:context="com.test.activity.sys.SplashActivity"> </LinearLayout>

初始页面自定义主题
<!-- 加载页面 -->
<activity
android:name=".activity.sys.SplashActivity"
android:theme="@style/SplashTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
   <style name="SplashTheme" parent="AppBaseTheme">
<!-- 欢迎页背景引用刚才写好的 -->
<item name="android:windowBackground">@drawable/splash</item>
<item name="android:windowFullscreen">true</item>
<!-- <item name="android:windowIsTranslucent">true</item> --> <!-- 透明背景 -->
</style>

update_app_progress.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/update_app_progress"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@color/bg_gray"
android:orientation="vertical" > <RelativeLayout
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_marginTop="10dp"> <TextView
android:id="@+id/downloadSize"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="--M/--M"
android:textSize="10sp"/> <TextView
android:id="@+id/netSpeed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="10dp"
android:text="---K/s"
android:textSize="10sp"/> <TextView
android:id="@+id/tvProgress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="--.--%"
android:textSize="10sp"/> </RelativeLayout> <com.test.view.NumberProgressBar
android:id="@+id/pbProgress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:progress_reached_bar_height="1.5dp"
app:progress_reached_color="#3498DB"
app:progress_text_color="#3498DB"
app:progress_text_size="10sp"
app:progress_unreached_bar_height="0.75dp"
app:progress_unreached_color="#CCCCCC"/>
</LinearLayout>
NumberProgressBar 为okGo中的view
/*
* Copyright 2016 jeasonlzy(廖子尧)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.test.view; import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.view.View; import com.test.R; /**
* ================================================
* 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy
* 版 本:1.0
* 创建日期:16/9/11
* 描 述:
* 修订历史:
* ================================================
*/
public class NumberProgressBar extends View { public interface OnProgressBarListener { void onProgressChange(int current, int max);
} private int mMaxProgress = 100; /**
* Current progress, can not exceed the max progress.
*/
private int mCurrentProgress = 0; /**
* The progress area bar color.
*/
private int mReachedBarColor; /**
* The bar unreached area color.
*/
private int mUnreachedBarColor; /**
* The progress text color.
*/
private int mTextColor; /**
* The progress text size.
*/
private float mTextSize; /**
* The height of the reached area.
*/
private float mReachedBarHeight; /**
* The height of the unreached area.
*/
private float mUnreachedBarHeight; /**
* The suffix of the number.
*/
private String mSuffix = "%"; /**
* The prefix.
*/
private String mPrefix = ""; private final int default_text_color = Color.rgb(66, 145, 241);
private final int default_reached_color = Color.rgb(66, 145, 241);
private final int default_unreached_color = Color.rgb(204, 204, 204);
private final float default_progress_text_offset;
private final float default_text_size;
private final float default_reached_bar_height;
private final float default_unreached_bar_height; /**
* For save and restore instance of progressbar.
*/
private static final String INSTANCE_STATE = "saved_instance";
private static final String INSTANCE_TEXT_COLOR = "text_color";
private static final String INSTANCE_TEXT_SIZE = "text_size";
private static final String INSTANCE_REACHED_BAR_HEIGHT = "reached_bar_height";
private static final String INSTANCE_REACHED_BAR_COLOR = "reached_bar_color";
private static final String INSTANCE_UNREACHED_BAR_HEIGHT = "unreached_bar_height";
private static final String INSTANCE_UNREACHED_BAR_COLOR = "unreached_bar_color";
private static final String INSTANCE_MAX = "max";
private static final String INSTANCE_PROGRESS = "progress";
private static final String INSTANCE_SUFFIX = "suffix";
private static final String INSTANCE_PREFIX = "prefix";
private static final String INSTANCE_TEXT_VISIBILITY = "text_visibility"; private static final int PROGRESS_TEXT_VISIBLE = 0; /**
* The width of the text that to be drawn.
*/
private float mDrawTextWidth; /**
* The drawn text start.
*/
private float mDrawTextStart; /**
* The drawn text end.
*/
private float mDrawTextEnd; /**
* The text that to be drawn in onDraw().
*/
private String mCurrentDrawText; /**
* The Paint of the reached area.
*/
private Paint mReachedBarPaint;
/**
* The Paint of the unreached area.
*/
private Paint mUnreachedBarPaint;
/**
* The Paint of the progress text.
*/
private Paint mTextPaint; /**
* Unreached bar area to draw rect.
*/
private RectF mUnreachedRectF = new RectF(0, 0, 0, 0);
/**
* Reached bar area rect.
*/
private RectF mReachedRectF = new RectF(0, 0, 0, 0); /**
* The progress text offset.
*/
private float mOffset; /**
* Determine if need to draw unreached area.
*/
private boolean mDrawUnreachedBar = true; private boolean mDrawReachedBar = true; private boolean mIfDrawText = true; /**
* Listener
*/
private OnProgressBarListener mListener; public enum ProgressTextVisibility {
Visible, Invisible
} public NumberProgressBar(Context context) {
this(context, null);
} public NumberProgressBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
} public NumberProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr); default_reached_bar_height = dp2px(1.5f);
default_unreached_bar_height = dp2px(1.0f);
default_text_size = sp2px(10);
default_progress_text_offset = dp2px(3.0f); //load styled attributes.
final TypedArray attributes = context.getTheme().obtainStyledAttributes(attrs, R.styleable.NumberProgressBar, defStyleAttr, 0); mReachedBarColor = attributes.getColor(R.styleable.NumberProgressBar_progress_reached_color, default_reached_color);
mUnreachedBarColor = attributes.getColor(R.styleable.NumberProgressBar_progress_unreached_color, default_unreached_color);
mTextColor = attributes.getColor(R.styleable.NumberProgressBar_progress_text_color, default_text_color);
mTextSize = attributes.getDimension(R.styleable.NumberProgressBar_progress_text_size, default_text_size); mReachedBarHeight = attributes.getDimension(R.styleable.NumberProgressBar_progress_reached_bar_height, default_reached_bar_height);
mUnreachedBarHeight = attributes.getDimension(R.styleable.NumberProgressBar_progress_unreached_bar_height, default_unreached_bar_height);
mOffset = attributes.getDimension(R.styleable.NumberProgressBar_progress_text_offset, default_progress_text_offset); int textVisible = attributes.getInt(R.styleable.NumberProgressBar_progress_text_visibility, PROGRESS_TEXT_VISIBLE);
if (textVisible != PROGRESS_TEXT_VISIBLE) {
mIfDrawText = false;
} setProgress(attributes.getInt(R.styleable.NumberProgressBar_progress_current, 0));
setMax(attributes.getInt(R.styleable.NumberProgressBar_progress_max, 100)); attributes.recycle();
initializePainters();
} @Override
protected int getSuggestedMinimumWidth() {
return (int) mTextSize;
} @Override
protected int getSuggestedMinimumHeight() {
return Math.max((int) mTextSize, Math.max((int) mReachedBarHeight, (int) mUnreachedBarHeight));
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(measure(widthMeasureSpec, true), measure(heightMeasureSpec, false));
} private int measure(int measureSpec, boolean isWidth) {
int result;
int mode = MeasureSpec.getMode(measureSpec);
int size = MeasureSpec.getSize(measureSpec);
int padding = isWidth ? getPaddingLeft() + getPaddingRight() : getPaddingTop() + getPaddingBottom();
if (mode == MeasureSpec.EXACTLY) {
result = size;
} else {
result = isWidth ? getSuggestedMinimumWidth() : getSuggestedMinimumHeight();
result += padding;
if (mode == MeasureSpec.AT_MOST) {
if (isWidth) {
result = Math.max(result, size);
} else {
result = Math.min(result, size);
}
}
}
return result;
} @Override
protected void onDraw(Canvas canvas) {
if (mIfDrawText) {
calculateDrawRectF();
} else {
calculateDrawRectFWithoutProgressText();
} if (mDrawReachedBar) {
canvas.drawRect(mReachedRectF, mReachedBarPaint);
} if (mDrawUnreachedBar) {
canvas.drawRect(mUnreachedRectF, mUnreachedBarPaint);
} if (mIfDrawText) canvas.drawText(mCurrentDrawText, mDrawTextStart, mDrawTextEnd, mTextPaint);
} private void initializePainters() {
mReachedBarPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mReachedBarPaint.setColor(mReachedBarColor); mUnreachedBarPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mUnreachedBarPaint.setColor(mUnreachedBarColor); mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setColor(mTextColor);
mTextPaint.setTextSize(mTextSize);
} private void calculateDrawRectFWithoutProgressText() {
mReachedRectF.left = getPaddingLeft();
mReachedRectF.top = getHeight() / 2.0f - mReachedBarHeight / 2.0f;
mReachedRectF.right = (getWidth() - getPaddingLeft() - getPaddingRight()) / (getMax() * 1.0f) * getProgress() + getPaddingLeft();
mReachedRectF.bottom = getHeight() / 2.0f + mReachedBarHeight / 2.0f; mUnreachedRectF.left = mReachedRectF.right;
mUnreachedRectF.right = getWidth() - getPaddingRight();
mUnreachedRectF.top = getHeight() / 2.0f + -mUnreachedBarHeight / 2.0f;
mUnreachedRectF.bottom = getHeight() / 2.0f + mUnreachedBarHeight / 2.0f;
} private void calculateDrawRectF() { mCurrentDrawText = String.format("%d", getProgress() * 100 / getMax());
mCurrentDrawText = mPrefix + mCurrentDrawText + mSuffix;
mDrawTextWidth = mTextPaint.measureText(mCurrentDrawText); if (getProgress() == 0) {
mDrawReachedBar = false;
mDrawTextStart = getPaddingLeft();
} else {
mDrawReachedBar = true;
mReachedRectF.left = getPaddingLeft();
mReachedRectF.top = getHeight() / 2.0f - mReachedBarHeight / 2.0f;
mReachedRectF.right = (getWidth() - getPaddingLeft() - getPaddingRight()) / (getMax() * 1.0f) * getProgress() - mOffset + getPaddingLeft();
mReachedRectF.bottom = getHeight() / 2.0f + mReachedBarHeight / 2.0f;
mDrawTextStart = (mReachedRectF.right + mOffset);
} mDrawTextEnd = (int) ((getHeight() / 2.0f) - ((mTextPaint.descent() + mTextPaint.ascent()) / 2.0f)); if ((mDrawTextStart + mDrawTextWidth) >= getWidth() - getPaddingRight()) {
mDrawTextStart = getWidth() - getPaddingRight() - mDrawTextWidth;
mReachedRectF.right = mDrawTextStart - mOffset;
} float unreachedBarStart = mDrawTextStart + mDrawTextWidth + mOffset;
if (unreachedBarStart >= getWidth() - getPaddingRight()) {
mDrawUnreachedBar = false;
} else {
mDrawUnreachedBar = true;
mUnreachedRectF.left = unreachedBarStart;
mUnreachedRectF.right = getWidth() - getPaddingRight();
mUnreachedRectF.top = getHeight() / 2.0f + -mUnreachedBarHeight / 2.0f;
mUnreachedRectF.bottom = getHeight() / 2.0f + mUnreachedBarHeight / 2.0f;
}
} /**
* Get progress text color.
*
* @return progress text color.
*/
public int getTextColor() {
return mTextColor;
} /**
* Get progress text size.
*
* @return progress text size.
*/
public float getProgressTextSize() {
return mTextSize;
} public int getUnreachedBarColor() {
return mUnreachedBarColor;
} public int getReachedBarColor() {
return mReachedBarColor;
} public int getProgress() {
return mCurrentProgress;
} public int getMax() {
return mMaxProgress;
} public float getReachedBarHeight() {
return mReachedBarHeight;
} public float getUnreachedBarHeight() {
return mUnreachedBarHeight;
} public void setProgressTextSize(float textSize) {
this.mTextSize = textSize;
mTextPaint.setTextSize(mTextSize);
invalidate();
} public void setProgressTextColor(int textColor) {
this.mTextColor = textColor;
mTextPaint.setColor(mTextColor);
invalidate();
} public void setUnreachedBarColor(int barColor) {
this.mUnreachedBarColor = barColor;
mUnreachedBarPaint.setColor(mUnreachedBarColor);
invalidate();
} public void setReachedBarColor(int progressColor) {
this.mReachedBarColor = progressColor;
mReachedBarPaint.setColor(mReachedBarColor);
invalidate();
} public void setReachedBarHeight(float height) {
mReachedBarHeight = height;
} public void setUnreachedBarHeight(float height) {
mUnreachedBarHeight = height;
} public void setMax(int maxProgress) {
if (maxProgress > 0) {
this.mMaxProgress = maxProgress;
invalidate();
}
} public void setSuffix(String suffix) {
if (suffix == null) {
mSuffix = "";
} else {
mSuffix = suffix;
}
} public String getSuffix() {
return mSuffix;
} public void setPrefix(String prefix) {
if (prefix == null) mPrefix = "";
else {
mPrefix = prefix;
}
} public String getPrefix() {
return mPrefix;
} public void incrementProgressBy(int by) {
if (by > 0) {
setProgress(getProgress() + by);
} if (mListener != null) {
mListener.onProgressChange(getProgress(), getMax());
}
} public void setProgress(int progress) {
if (progress <= getMax() && progress >= 0) {
this.mCurrentProgress = progress;
invalidate();
}
} @Override
protected Parcelable onSaveInstanceState() {
final Bundle bundle = new Bundle();
bundle.putParcelable(INSTANCE_STATE, super.onSaveInstanceState());
bundle.putInt(INSTANCE_TEXT_COLOR, getTextColor());
bundle.putFloat(INSTANCE_TEXT_SIZE, getProgressTextSize());
bundle.putFloat(INSTANCE_REACHED_BAR_HEIGHT, getReachedBarHeight());
bundle.putFloat(INSTANCE_UNREACHED_BAR_HEIGHT, getUnreachedBarHeight());
bundle.putInt(INSTANCE_REACHED_BAR_COLOR, getReachedBarColor());
bundle.putInt(INSTANCE_UNREACHED_BAR_COLOR, getUnreachedBarColor());
bundle.putInt(INSTANCE_MAX, getMax());
bundle.putInt(INSTANCE_PROGRESS, getProgress());
bundle.putString(INSTANCE_SUFFIX, getSuffix());
bundle.putString(INSTANCE_PREFIX, getPrefix());
bundle.putBoolean(INSTANCE_TEXT_VISIBILITY, getProgressTextVisibility());
return bundle;
} @Override
protected void onRestoreInstanceState(Parcelable state) {
if (state instanceof Bundle) {
final Bundle bundle = (Bundle) state;
mTextColor = bundle.getInt(INSTANCE_TEXT_COLOR);
mTextSize = bundle.getFloat(INSTANCE_TEXT_SIZE);
mReachedBarHeight = bundle.getFloat(INSTANCE_REACHED_BAR_HEIGHT);
mUnreachedBarHeight = bundle.getFloat(INSTANCE_UNREACHED_BAR_HEIGHT);
mReachedBarColor = bundle.getInt(INSTANCE_REACHED_BAR_COLOR);
mUnreachedBarColor = bundle.getInt(INSTANCE_UNREACHED_BAR_COLOR);
initializePainters();
setMax(bundle.getInt(INSTANCE_MAX));
setProgress(bundle.getInt(INSTANCE_PROGRESS));
setPrefix(bundle.getString(INSTANCE_PREFIX));
setSuffix(bundle.getString(INSTANCE_SUFFIX));
setProgressTextVisibility(bundle.getBoolean(INSTANCE_TEXT_VISIBILITY) ? ProgressTextVisibility.Visible : ProgressTextVisibility.Invisible);
super.onRestoreInstanceState(bundle.getParcelable(INSTANCE_STATE));
return;
}
super.onRestoreInstanceState(state);
} public float dp2px(float dp) {
final float scale = getResources().getDisplayMetrics().density;
return dp * scale + 0.5f;
} public float sp2px(float sp) {
final float scale = getResources().getDisplayMetrics().scaledDensity;
return sp * scale;
} public void setProgressTextVisibility(ProgressTextVisibility visibility) {
mIfDrawText = visibility == ProgressTextVisibility.Visible;
invalidate();
} public boolean getProgressTextVisibility() {
return mIfDrawText;
} public void setOnProgressBarListener(OnProgressBarListener listener) {
mListener = listener;
}
}

Android 6.0 7.0 8.0 一个简单的app内更新版本-okgo app版本更新的更多相关文章

  1. 一个简单的数据增量更新策略(Android / MongoDB / Django)

    我在做个人APP - CayKANJI - 的时候遇到一个问题: 如何增量式地把日语汉字数据地从server更新到APP端,即每次用户运行更新操作时,仅仅获取版本号高于本地缓存的内容. 数据格式 为了 ...

  2. Android UI开发: 横向ListView(HorizontalListView)及一个简单相册的完整实现 (附源码下载)

    http://blog.csdn.net/yanzi1225627/article/details/21294553 原文

  3. 用.netcore写一个简单redis驱动,调试windows版本的redis.平且给set和get命令添加参数.

    1. 下载windows版本的redis 2.开发环境vs2017  新建一个 .net core控制台. private static Socket socket = new Socket(Addr ...

  4. 实现一个简单的WebSocket聊天室

    WebSocket 简介 WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议. WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主 ...

  5. SmartSql使用教程(1)——初探,建立一个简单的CURD接口服务

    一.引言 最近SmartSql被正式引入到了NCC,借着这个契机写一个使用教程系列 二.SmartSql简介[摘自官方文档] 1. SmartSql是什么? SmartSql = MyBatis + ...

  6. Django入门第一步:构建一个简单的Django项目

    Django入门第一步:构建一个简单的Django项目 1.简介 Django是一个功能完备的Python Web框架,可用于构建复杂的Web应用程序.在本文中,将通过示例跳入并学习Django.您将 ...

  7. Android requires compiler compliance level 5.0 or 6.0. Found '1.7' instead. Please use Android Tool

    重装操作系统后,要重新配置Android开发环境.配置成功后,添加原本项目时却出现了错误! Android requires compiler compliance level 5.0 or 6.0. ...

  8. Android 自定义View修炼-仿QQ5.0 的侧滑菜单效果的实现

    有一段时间没有写博客了,最近比较忙,没什么时间写,刚好今天有点时间, 我就分享下,侧滑菜单的实现原理,一般android侧滑的实现原理和步骤如下:(源码下载在下面最后给出哈) 1.使用ViewGrou ...

  9. Android获取设备隐私 忽略6.0权限管理

    1.前言 (1).由于MIUI等部分国产定制系统也有权限管理,没有相关api,故无法判断用户是否允许获取联系人等隐私.在Android 6.0之后,新增权限管理可以通过官方api判断用户的运行状态: ...

随机推荐

  1. Sdn - 基础题试水

    ## sdn - 初步分析基于OpenFlow的SDN网络控制功能 题目要求: 1.下发流表项实现 h1 和 h2,h2 和 h3 不能互通.h1 和 h3 可互通. 2.结合捕获的 SDN 相关协议 ...

  2. SpringMVC中Controller的返回值类型

    Controller方法的返回值可以有以下几种: 1.返回ModelAndView 返回ModelAndView时最常见的一种返回结果.需要在方法结束的时候定义一个ModelAndView对象,并对M ...

  3. Unity发布Windows程序遇到的问题

    Unity版本:5.6.2 因为程序中使用了Networking模块,所以在打包发布的时候需要登录Unity的账号,并做设置. 错误信息如下: 解决办法如下: 先登录Unity账号,并在Service ...

  4. iOS开发面试题(中级)

    //想面试的童鞋们来看看自己会多少, 老鸟可以无视直接绕过...1. Object-c的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么?与Ex ...

  5. Enterprise Library 6.0 参考源码索引

    http://www.projky.com/entlib/6.0/Diagnostics/Tracing/DiaLib.cs.htmlhttp://www.projky.com/entlib/6.0/ ...

  6. Hive如何加载和导入HBase的数据

    当我们用HBase 存储实时数据的时候, 如果要做一些数据分析方面的操作, 就比较困难了, 要写MapReduce Job. Hive 主要是用来做数据分析的数据仓库,支持标准SQL 查询, 做数据分 ...

  7. XLSReadWriteII5使用示例

    之前一直是使用XLSReadWriteII4,今天更新到XLSReadWriteII5,测试了一下,发现一些操作变化比较大,现将XLSReadWriteII5的使用示例写一下,以下是代码和生成的exc ...

  8. Eslint 配置及规则说明(报错)

    https://blog.csdn.net/violetjack0808/article/details/72620859 https://blog.csdn.net/hsl0530hsl/artic ...

  9. String、StringBuffer与StringBuilder比较

    关于这三个类在字符串处理中的位置不言而喻,那么他们到底有什么优缺点,到底什么时候该用谁呢?下面我们从以下几点说明一下 1.三者在执行速度方面的比较:     StringBuilder > St ...

  10. 计算机网络【8】—— Get和Post请求的区别

    get参数通过url传递,post放在request body中. get请求在url中传递的参数是有长度限制的,而post没有. get比post更不安全,因为参数直接暴露在url中,所以不能用来传 ...