APK检查更新,代码如下:
/** * 版本更新 */ // 下载进度条 private ProgressBar progressBar; // 是否终止下载 private boolean isInterceptDownload = false; //进度条显示数值 private int progress = 0; //获取的下载链接 private String apkDwonloadUrl = ""; private String netVercode; private String disableCode; private int localVercode; private String updateFunction; /** * 声明一个handler来跟进进度条 */ private Handler handler = new Handler() { public void handleMessage(android.os.Message msg) { switch (msg.what) { case 0x111: // 更新进度情况 progressBar.setProgress(progress); break; case 0x222: progressBar.setVisibility(View.INVISIBLE); // 安装apk文件 installApk(); break; default: break; } } }; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); inHandler(); } /** * 进入当前页面后5分钟开始检测版本(时间可自定义) */ private void inHandler() { new Handler().postDelayed(new Runnable() { @Override public void run() { doCheckVersion();//自动检测版本更新 } }, 100000 * 3); } /** * 版本更新请求 */ private void doCheckVersion() { //如果当前的版本号小于服务器的版本号就弹出版本更新dialog if (netVercode > localVercode) { LogUtils.d("版本需要更新"); showUpdateDialog(); } else { LogUtils.d("此版本为最新版本,无需更新"); } } /** * 提示更新对话框 * <p/> * 版本信息对象 */ private void showUpdateDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); builder.setTitle(R.string.versionUpdate); builder.setMessage(updateFunction); builder.setCancelable(false); builder.setPositiveButton(R.string.download, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); // 弹出下载框 showDownloadDialog(); } }); builder.setNegativeButton(R.string.talkLater, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); builder.create().show(); } /** * 弹出下载框 */ private void showDownloadDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); builder.setTitle(R.string.versionUpdateing); builder.setCancelable(false); final LayoutInflater inflater = LayoutInflater.from(MainActivity.this); View v = inflater.inflate(R.layout.activity_update_prgress, null); progressBar = (ProgressBar) v.findViewById(R.id.pb_update_progress); builder.setView(v); builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); //终止下载 isInterceptDownload = true; } }); builder.create().show(); //下载apk downloadApk(); } /** * 下载apk */ private void downloadApk() { //开启另一线程下载 Thread downLoadThread = new Thread(downApkRunnable); downLoadThread.start(); } /** * 从服务器下载新版apk的线程 */ private Runnable downApkRunnable = new Runnable() { @Override public void run() { if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { //如果没有SD卡 AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); builder.setTitle(R.string.houseKeeperHint); builder.setMessage(R.string.loadHintInfo); builder.setPositiveButton(R.string.sure, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); builder.show(); } else { try { //服务器上新版apk地址 java.net.URL url = new java.net.URL(apkDwonloadUrl); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.connect(); int length = conn.getContentLength(); InputStream is = conn.getInputStream(); File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/updateApkFile/"); if (!file.exists()) { //如果文件夹不存在,则创建 file.mkdir(); } //下载服务器中新版本软件(写文件) String apkFile = Environment.getExternalStorageDirectory().getAbsolutePath() + "/updateApkFile/" + AppUtils.getVersionName(MainActivity.this); 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); // handler.sendEmptyMessage(1); android.os.Message message_ = new android.os.Message(); message_.what = 0x111; handler.sendMessage(message_); if (numRead <= 0) { //下载完成通知安装 // handler.sendEmptyMessage(0); android.os.Message message = new android.os.Message(); message.what = 0x222; handler.sendMessage(message); break; } fos.write(buf, 0, numRead); //当点击取消时,则停止下载 } while (!isInterceptDownload); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } }; /** * 安装apk */ private void installApk() { // 获取当前sdcard存储路径 File apkFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/updateApkFile/" + AppUtils.getVersionName(MainActivity.this)); if (!apkFile.exists()) { return; } Intent i = new Intent(Intent.ACTION_VIEW); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 安装,如果签名不一致,可能出现程序未安装提示 i.setDataAndType(Uri.fromFile(new File(apkFile.getAbsolutePath())), "application/vnd.android.package-archive"); MainActivity.this.startActivity(i); android.os.Process.killProcess(android.os.Process.myPid()); }
权限管理:
//读写权限
private static String[] PERMISSIONS_STORAGE = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE};
//判断是否含有权限 boolean hasPermission = PermissionsManager.getInstance() .hasAllPermissions(SettingActivity.this, PERMISSIONS_STORAGE); if (hasPermission) { //含有权限,访问 showUpdateDialog(); } else { //不含权限,弹出开启权限窗 PermissionsManager.getInstance(). requestPermissionsIfNecessaryForResult(SettingActivity.this, PERMISSIONS_STORAGE, new PermissionsResultAction() { //同意开启权限 @Override public void onGranted() { LogUtils.i(TAG + "同意开启权限"); showUpdateDialog(); } //拒绝开启权限 @Override public void onDenied(String permission) { String message = String.format(Locale.getDefault(), "该权限是必须权限,不开启将影响APP使用", permission); Toast.makeText(SettingActivity.this, message, Toast.LENGTH_SHORT).show(); } } ); }
//权限管理工具类
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.util.Log;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
/**
* Created by xiaoMan on 2016/9/18.
* detail:A class to help you manage your permissions simply.
* 权限管理工具类
*/
public class PermissionsManager {
private static final String TAG = PermissionsManager.class.getSimpleName();
private final Set<String> mPendingRequests = new HashSet<>(1);
private final Set<String> mPermissions = new HashSet<>(1);
private final List<WeakReference<PermissionsResultAction>> mPendingActions = new ArrayList<>(1);
private static PermissionsManager mInstance = null;
public static PermissionsManager getInstance() {
if (mInstance == null) {
mInstance = new PermissionsManager();
}
return mInstance;
}
private PermissionsManager() {
initializePermissionsMap();
}
/**
* This method uses reflection to read all the permissions in the Manifest class.
* This is necessary because some permissions do not exist on older versions of Android,
* since they do not exist, they will be denied when you check whether you have permission
* which is problematic since a new permission is often added where there was no previous
* permission required. We initialize a Set of available permissions and check the set
* when checking if we have permission since we want to know when we are denied a permission
* because it doesn't exist yet.
*/
private synchronized void initializePermissionsMap() {
Field[] fields = Manifest.permission.class.getFields();
for (Field field : fields) {
String name = null;
try {
name = (String) field.get("");
} catch (IllegalAccessException e) {
Log.e(TAG, "Could not access field", e);
}
mPermissions.add(name);
}
}
/**
* This method retrieves all the permissions declared in the application's manifest.
* It returns a non null array of permisions that can be declared.
*
* @param activity the Activity necessary to check what permissions we have.
* @return a non null array of permissions that are declared in the application manifest.
*/
@NonNull
private synchronized String[] getManifestPermissions(@NonNull final Activity activity) {
PackageInfo packageInfo = null;
List<String> list = new ArrayList<>(1);
try {
Log.d(TAG, activity.getPackageName());
packageInfo = activity.getPackageManager().getPackageInfo(activity.getPackageName(), PackageManager.GET_PERMISSIONS);
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG, "A problem occurred when retrieving permissions", e);
}
if (packageInfo != null) {
String[] permissions = packageInfo.requestedPermissions;
if (permissions != null) {
for (String perm : permissions) {
Log.d(TAG, "Manifest contained permission: " + perm);
list.add(perm);
}
}
}
return list.toArray(new String[list.size()]);
}
/**
* This method adds the {@link PermissionsResultAction} to the current list
* of pending actions that will be completed when the permissions are
* received. The list of permissions passed to this method are registered
* in the PermissionsResultAction object so that it will be notified of changes
* made to these permissions.
*
* @param permissions the required permissions for the action to be executed.
* @param action the action to add to the current list of pending actions.
*/
private synchronized void addPendingAction(@NonNull String[] permissions,
@Nullable PermissionsResultAction action) {
if (action == null) {
return;
}
action.registerPermissions(permissions);
mPendingActions.add(new WeakReference<>(action));
}
/**
* This method removes a pending action from the list of pending actions.
* It is used for cases where the permission has already been granted, so
* you immediately wish to remove the pending action from the queue and
* execute the action.
*
* @param action the action to remove
*/
private synchronized void removePendingAction(@Nullable PermissionsResultAction action) {
for (Iterator<WeakReference<PermissionsResultAction>> iterator = mPendingActions.iterator();
iterator.hasNext(); ) {
WeakReference<PermissionsResultAction> weakRef = iterator.next();
if (weakRef.get() == action || weakRef.get() == null) {
iterator.remove();
}
}
}
/**
* This static method can be used to check whether or not you have a specific permission.
* It is basically a less verbose method of using {@link ActivityCompat#checkSelfPermission(Context, String)}
* and will simply return a boolean whether or not you have the permission. If you pass
* in a null Context object, it will return false as otherwise it cannot check the permission.
* However, the Activity parameter is nullable so that you can pass in a reference that you
* are not always sure will be valid or not (e.g. getActivity() from Fragment).
*
* @param context the Context necessary to check the permission
* @param permission the permission to check
* @return true if you have been granted the permission, false otherwise
*/
@SuppressWarnings("unused")
public synchronized boolean hasPermission(@Nullable Context context, @NonNull String permission) {
return context != null && (ActivityCompat.checkSelfPermission(context, permission)
== PackageManager.PERMISSION_GRANTED || !mPermissions.contains(permission));
}
/**
* This static method can be used to check whether or not you have several specific permissions.
* It is simpler than checking using {@link ActivityCompat#checkSelfPermission(Context, String)}
* for each permission and will simply return a boolean whether or not you have all the permissions.
* If you pass in a null Context object, it will return false as otherwise it cannot check the
* permission. However, the Activity parameter is nullable so that you can pass in a reference
* that you are not always sure will be valid or not (e.g. getActivity() from Fragment).
*
* @param context the Context necessary to check the permission
* @param permissions the permissions to check
* @return true if you have been granted all the permissions, false otherwise
*/
@SuppressWarnings("unused")
public synchronized boolean hasAllPermissions(@Nullable Context context, @NonNull String[] permissions) {
if (context == null) {
return false;
}
boolean hasAllPermissions = true;
for (String perm : permissions) {
hasAllPermissions &= hasPermission(context, perm);
}
return hasAllPermissions;
}
/**
* This method will request all the permissions declared in your application manifest
* for the specified {@link PermissionsResultAction}. The purpose of this method is to enable
* all permissions to be requested at one shot. The PermissionsResultAction is used to notify
* you of the user allowing or denying each permission. The Activity and PermissionsResultAction
* parameters are both annotated Nullable, but this method will not work if the Activity
* is null. It is only annotated Nullable as a courtesy to prevent crashes in the case
* that you call this from a Fragment where {@link Fragment#getActivity()} could yield
* null. Additionally, you will not receive any notification of permissions being granted
* if you provide a null PermissionsResultAction.
*
* @param activity the Activity necessary to request and check permissions.
* @param action the PermissionsResultAction used to notify you of permissions being accepted.
*/
@SuppressWarnings("unused")
public synchronized void requestAllManifestPermissionsIfNecessary(final @Nullable Activity activity,
final @Nullable PermissionsResultAction action) {
if (activity == null) {
return;
}
String[] perms = getManifestPermissions(activity);
requestPermissionsIfNecessaryForResult(activity, perms, action);
}
/**
* This method should be used to execute a {@link PermissionsResultAction} for the array
* of permissions passed to this method. This method will request the permissions if
* they need to be requested (i.e. we don't have permission yet) and will add the
* PermissionsResultAction to the queue to be notified of permissions being granted or
* denied. In the case of pre-Android Marshmallow, permissions will be granted immediately.
* The Activity variable is nullable, but if it is null, the method will fail to execute.
* This is only nullable as a courtesy for Fragments where getActivity() may yeild null
* if the Fragment is not currently added to its parent Activity.
*
* @param activity the activity necessary to request the permissions.
* @param permissions the list of permissions to request for the {@link PermissionsResultAction}.
* @param action the PermissionsResultAction to notify when the permissions are granted or denied.
*/
@SuppressWarnings("unused")
public synchronized void requestPermissionsIfNecessaryForResult(@Nullable Activity activity,
@NonNull String[] permissions,
@Nullable PermissionsResultAction action) {
if (activity == null) {
return;
}
addPendingAction(permissions, action);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
doPermissionWorkBeforeAndroidM(activity, permissions, action);
} else {
List<String> permList = getPermissionsListToRequest(activity, permissions, action);
if (permList.isEmpty()) {
//if there is no permission to request, there is no reason to keep the action int the list
removePendingAction(action);
} else {
String[] permsToRequest = permList.toArray(new String[permList.size()]);
mPendingRequests.addAll(permList);
ActivityCompat.requestPermissions(activity, permsToRequest, 1);
}
}
}
/**
* This method should be used to execute a {@link PermissionsResultAction} for the array
* of permissions passed to this method. This method will request the permissions if
* they need to be requested (i.e. we don't have permission yet) and will add the
* PermissionsResultAction to the queue to be notified of permissions being granted or
* denied. In the case of pre-Android Marshmallow, permissions will be granted immediately.
* The Fragment variable is used, but if {@link Fragment#getActivity()} returns null, this method
* will fail to work as the activity reference is necessary to check for permissions.
*
* @param fragment the fragment necessary to request the permissions.
* @param permissions the list of permissions to request for the {@link PermissionsResultAction}.
* @param action the PermissionsResultAction to notify when the permissions are granted or denied.
*/
@SuppressWarnings("unused")
public synchronized void requestPermissionsIfNecessaryForResult(@NonNull Fragment fragment,
@NonNull String[] permissions,
@Nullable PermissionsResultAction action) {
Activity activity = fragment.getActivity();
if (activity == null) {
return;
}
addPendingAction(permissions, action);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
doPermissionWorkBeforeAndroidM(activity, permissions, action);
} else {
List<String> permList = getPermissionsListToRequest(activity, permissions, action);
if (permList.isEmpty()) {
//if there is no permission to request, there is no reason to keep the action int the list
removePendingAction(action);
} else {
String[] permsToRequest = permList.toArray(new String[permList.size()]);
mPendingRequests.addAll(permList);
fragment.requestPermissions(permsToRequest, 1);
}
}
}
/**
* This method notifies the PermissionsManager that the permissions have change. If you are making
* the permissions requests using an Activity, then this method should be called from the
* Activity callback onRequestPermissionsResult() with the variables passed to that method. If
* you are passing a Fragment to make the permissions request, then you should call this in
* the {@link Fragment#onRequestPermissionsResult(int, String[], int[])} method.
* It will notify all the pending PermissionsResultAction objects currently
* in the queue, and will remove the permissions request from the list of pending requests.
*
* @param permissions the permissions that have changed.
* @param results the values for each permission.
*/
@SuppressWarnings("unused")
public synchronized void notifyPermissionsChange(@NonNull String[] permissions, @NonNull int[] results) {
int size = permissions.length;
if (results.length < size) {
size = results.length;
}
Iterator<WeakReference<PermissionsResultAction>> iterator = mPendingActions.iterator();
while (iterator.hasNext()) {
PermissionsResultAction action = iterator.next().get();
for (int n = 0; n < size; n++) {
if (action == null || action.onResult(permissions[n], results[n])) {
iterator.remove();
break;
}
}
}
for (int n = 0; n < size; n++) {
mPendingRequests.remove(permissions[n]);
}
}
/**
* When request permissions on devices before Android M (Android 6.0, API Level 23)
* Do the granted or denied work directly according to the permission status
*
* @param activity the activity to check permissions
* @param permissions the permissions names
* @param action the callback work object, containing what we what to do after
* permission check
*/
private void doPermissionWorkBeforeAndroidM(@NonNull Activity activity,
@NonNull String[] permissions,
@Nullable PermissionsResultAction action) {
for (String perm : permissions) {
if (action != null) {
if (!mPermissions.contains(perm)) {
action.onResult(perm, Permissions.NOT_FOUND);
} else if (ActivityCompat.checkSelfPermission(activity, perm)
!= PackageManager.PERMISSION_GRANTED) {
action.onResult(perm, Permissions.DENIED);
} else {
action.onResult(perm, Permissions.GRANTED);
}
}
}
}
/**
* Filter the permissions list:
* If a permission is not granted, add it to the result list
* if a permission is granted, do the granted work, do not add it to the result list
*
* @param activity the activity to check permissions
* @param permissions all the permissions names
* @param action the callback work object, containing what we what to do after
* permission check
* @return a list of permissions names that are not granted yet
*/
@NonNull
private List<String> getPermissionsListToRequest(@NonNull Activity activity,
@NonNull String[] permissions,
@Nullable PermissionsResultAction action) {
List<String> permList = new ArrayList<>(permissions.length);
for (String perm : permissions) {
if (!mPermissions.contains(perm)) {
if (action != null) {
action.onResult(perm, Permissions.NOT_FOUND);
}
} else if (ActivityCompat.checkSelfPermission(activity, perm) != PackageManager.PERMISSION_GRANTED) {
if (!mPendingRequests.contains(perm)) {
permList.add(perm);
}
} else {
if (action != null) {
action.onResult(perm, Permissions.GRANTED);
}
}
}
return permList;
}
}
布局:activity_update_prgress.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <ProgressBar android:id="@+id/pb_update_progress" style="?android:attr/progressBarStyleHorizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="@dimen/x60" android:layout_marginLeft="5dp" android:layout_marginRight="5dp" android:layout_marginTop="30dp" android:indeterminate="false" android:max="100" android:progressDrawable="@drawable/progressbar_color" /> </LinearLayout>
progressbar_color.xml-------->
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@android:id/background"> <shape> <corners android:radius="5dp" /> <solid android:color="@color/colorLine" /> </shape> </item> <!-- 进度条 --> <item android:id="@android:id/progress" android:drawable="@drawable/update_progress"> <shape> <corners android:radius="5dp" /> </shape> </item> </layer-list>