Android 6.0 7.0 8.0 一个简单的app内更新版本-okgo app版本更新
登陆时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版本更新的更多相关文章
- 一个简单的数据增量更新策略(Android / MongoDB / Django)
我在做个人APP - CayKANJI - 的时候遇到一个问题: 如何增量式地把日语汉字数据地从server更新到APP端,即每次用户运行更新操作时,仅仅获取版本号高于本地缓存的内容. 数据格式 为了 ...
- Android UI开发: 横向ListView(HorizontalListView)及一个简单相册的完整实现 (附源码下载)
http://blog.csdn.net/yanzi1225627/article/details/21294553 原文
- 用.netcore写一个简单redis驱动,调试windows版本的redis.平且给set和get命令添加参数.
1. 下载windows版本的redis 2.开发环境vs2017 新建一个 .net core控制台. private static Socket socket = new Socket(Addr ...
- 实现一个简单的WebSocket聊天室
WebSocket 简介 WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议. WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主 ...
- SmartSql使用教程(1)——初探,建立一个简单的CURD接口服务
一.引言 最近SmartSql被正式引入到了NCC,借着这个契机写一个使用教程系列 二.SmartSql简介[摘自官方文档] 1. SmartSql是什么? SmartSql = MyBatis + ...
- Django入门第一步:构建一个简单的Django项目
Django入门第一步:构建一个简单的Django项目 1.简介 Django是一个功能完备的Python Web框架,可用于构建复杂的Web应用程序.在本文中,将通过示例跳入并学习Django.您将 ...
- 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. ...
- Android 自定义View修炼-仿QQ5.0 的侧滑菜单效果的实现
有一段时间没有写博客了,最近比较忙,没什么时间写,刚好今天有点时间, 我就分享下,侧滑菜单的实现原理,一般android侧滑的实现原理和步骤如下:(源码下载在下面最后给出哈) 1.使用ViewGrou ...
- Android获取设备隐私 忽略6.0权限管理
1.前言 (1).由于MIUI等部分国产定制系统也有权限管理,没有相关api,故无法判断用户是否允许获取联系人等隐私.在Android 6.0之后,新增权限管理可以通过官方api判断用户的运行状态: ...
随机推荐
- Sdn - 基础题试水
## sdn - 初步分析基于OpenFlow的SDN网络控制功能 题目要求: 1.下发流表项实现 h1 和 h2,h2 和 h3 不能互通.h1 和 h3 可互通. 2.结合捕获的 SDN 相关协议 ...
- SpringMVC中Controller的返回值类型
Controller方法的返回值可以有以下几种: 1.返回ModelAndView 返回ModelAndView时最常见的一种返回结果.需要在方法结束的时候定义一个ModelAndView对象,并对M ...
- Unity发布Windows程序遇到的问题
Unity版本:5.6.2 因为程序中使用了Networking模块,所以在打包发布的时候需要登录Unity的账号,并做设置. 错误信息如下: 解决办法如下: 先登录Unity账号,并在Service ...
- iOS开发面试题(中级)
//想面试的童鞋们来看看自己会多少, 老鸟可以无视直接绕过...1. Object-c的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么?与Ex ...
- Enterprise Library 6.0 参考源码索引
http://www.projky.com/entlib/6.0/Diagnostics/Tracing/DiaLib.cs.htmlhttp://www.projky.com/entlib/6.0/ ...
- Hive如何加载和导入HBase的数据
当我们用HBase 存储实时数据的时候, 如果要做一些数据分析方面的操作, 就比较困难了, 要写MapReduce Job. Hive 主要是用来做数据分析的数据仓库,支持标准SQL 查询, 做数据分 ...
- XLSReadWriteII5使用示例
之前一直是使用XLSReadWriteII4,今天更新到XLSReadWriteII5,测试了一下,发现一些操作变化比较大,现将XLSReadWriteII5的使用示例写一下,以下是代码和生成的exc ...
- Eslint 配置及规则说明(报错)
https://blog.csdn.net/violetjack0808/article/details/72620859 https://blog.csdn.net/hsl0530hsl/artic ...
- String、StringBuffer与StringBuilder比较
关于这三个类在字符串处理中的位置不言而喻,那么他们到底有什么优缺点,到底什么时候该用谁呢?下面我们从以下几点说明一下 1.三者在执行速度方面的比较: StringBuilder > St ...
- 计算机网络【8】—— Get和Post请求的区别
get参数通过url传递,post放在request body中. get请求在url中传递的参数是有长度限制的,而post没有. get比post更不安全,因为参数直接暴露在url中,所以不能用来传 ...