Created
October 8, 2016 15:39
-
-
Save leov1/398e82cbe866115bc654c909221fe286 to your computer and use it in GitHub Desktop.
Android Update Service Notification show progress with permission request
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
此处 只 添加 调起处的代码 | |
activity implements EasyPermissions.PermissionCallbacks | |
@AfterPermissionGranted(RC_STORE_PERM) | |
private void startCheckUpdate() { | |
if (EasyPermissions.hasPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE})) { | |
// Have permission, do the thing! | |
new UpdateUtils(AboutActivity.this, true).checkUpdate(); | |
} else { | |
// Ask for one permission | |
EasyPermissions.requestPermissions(this, getString(R.string.permission_denied_store), | |
RC_STORE_PERM, Manifest.permission.WRITE_EXTERNAL_STORAGE); | |
} | |
} | |
重写: | |
@Override | |
public void onPermissionsGranted(int requestCode, List<String> perms) { | |
new UpdateUtils(AboutActivity.this, true).checkUpdate(); | |
} | |
@Override | |
public void onPermissionsDenied(int requestCode, List<String> perms) { | |
if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) { | |
new AppSettingsDialog.Builder(this, getString(R.string.rationale_ask_again)) | |
.setTitle(getString(R.string.title_settings_dialog)) | |
.setPositiveButton(getString(R.string.setting)) | |
.setNegativeButton(getString(R.string.cancel), null /* click listener */) | |
.setRequestCode(RC_SETTINGS_SCREEN) | |
.build() | |
.show(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
compile 'pub.devrel:easypermissions:0.2.0' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class DialogHelp { | |
/*** | |
* 获取一个dialog | |
* | |
* @param context | |
* @return | |
*/ | |
public static AlertDialog.Builder getDialog(Context context) { | |
AlertDialog.Builder builder = new AlertDialog.Builder(context); | |
return builder; | |
} | |
/*** | |
* 获取一个耗时等待对话框 | |
* | |
* @param context | |
* @param message | |
* @return | |
*/ | |
public static ProgressDialog getWaitDialog(Context context, String message) { | |
ProgressDialog waitDialog = new ProgressDialog(context); | |
if (!TextUtils.isEmpty(message)) { | |
waitDialog.setMessage(message); | |
} | |
return waitDialog; | |
} | |
/*** | |
* 获取一个信息对话框,注意需要自己手动调用show方法显示 | |
* | |
* @param context | |
* @param message | |
* @param onClickListener | |
* @return | |
*/ | |
public static AlertDialog.Builder getMessageDialog(Context context, String message, DialogInterface.OnClickListener onClickListener) { | |
AlertDialog.Builder builder = getDialog(context); | |
builder.setMessage(message); | |
builder.setPositiveButton("确定", onClickListener); | |
return builder; | |
} | |
public static AlertDialog.Builder getMessageDialog(Context context, String message) { | |
return getMessageDialog(context, message, null); | |
} | |
public static AlertDialog.Builder getConfirmDialog(Context context, String message, DialogInterface.OnClickListener onClickListener) { | |
AlertDialog.Builder builder = getDialog(context); | |
builder.setMessage(Html.fromHtml(message)); | |
builder.setPositiveButton("确定", onClickListener); | |
builder.setNegativeButton("取消", null); | |
return builder; | |
} | |
public static AlertDialog.Builder getConfirmDialog(Context context, String message, DialogInterface.OnClickListener onOkClickListener, DialogInterface.OnClickListener onCancleClickListener) { | |
AlertDialog.Builder builder = getDialog(context); | |
builder.setMessage(message); | |
builder.setPositiveButton("确定", onOkClickListener); | |
builder.setNegativeButton("取消", onCancleClickListener); | |
return builder; | |
} | |
public static AlertDialog.Builder getSelectDialog(Context context, String title, String[] arrays, DialogInterface.OnClickListener onClickListener) { | |
AlertDialog.Builder builder = getDialog(context); | |
builder.setItems(arrays, onClickListener); | |
if (!TextUtils.isEmpty(title)) { | |
builder.setTitle(title); | |
} | |
builder.setPositiveButton("取消", null); | |
return builder; | |
} | |
public static AlertDialog.Builder getSelectDialog(Context context, String[] arrays, DialogInterface.OnClickListener onClickListener) { | |
return getSelectDialog(context, "", arrays, onClickListener); | |
} | |
public static AlertDialog.Builder getSingleChoiceDialog(Context context, String title, String[] arrays, int selectIndex, DialogInterface.OnClickListener onClickListener) { | |
AlertDialog.Builder builder = getDialog(context); | |
builder.setSingleChoiceItems(arrays, selectIndex, onClickListener); | |
if (!TextUtils.isEmpty(title)) { | |
builder.setTitle(title); | |
} | |
builder.setNegativeButton("取消", null); | |
return builder; | |
} | |
public static AlertDialog.Builder getSingleChoiceDialog(Context context, String[] arrays, int selectIndex, DialogInterface.OnClickListener onClickListener) { | |
return getSingleChoiceDialog(context, "", arrays, selectIndex, onClickListener); | |
} | |
/** | |
* 得到自定义的progressDialog | |
* | |
* @param context | |
* @param msg | |
* @return | |
*/ | |
public static Dialog createLoadingDialog(Context context, String msg) { | |
LayoutInflater inflater = LayoutInflater.from(context); | |
View v = inflater.inflate(R.layout.loading_layout, null);// 得到加载view | |
LinearLayout layout = (LinearLayout) v.findViewById(R.id.dialog_view);// 加载布局 | |
// main.xml中的ImageView | |
ImageView spaceshipImage = (ImageView) v.findViewById(R.id.loading_img); | |
TextView tipTextView = (TextView) v.findViewById(R.id.loading_text);// 提示文字 | |
// 加载动画 | |
Animation hyperspaceJumpAnimation = AnimationUtils.loadAnimation( | |
context, R.anim.loading_animation); | |
// 使用ImageView显示动画 | |
spaceshipImage.startAnimation(hyperspaceJumpAnimation); | |
tipTextView.setText(msg);// 设置加载信息 | |
Dialog loadingDialog = new Dialog(context, R.style.loading);// 创建自定义样式dialog | |
loadingDialog.setCancelable(false);// 不可以用“返回键”取消 | |
loadingDialog.setContentView(layout, new LinearLayout.LayoutParams( | |
LinearLayout.LayoutParams.FILL_PARENT, | |
LinearLayout.LayoutParams.FILL_PARENT));// 设置布局 | |
return loadingDialog; | |
} | |
public static Dialog showLoadingDialog(Context context) { | |
AlertDialog.Builder builder = new AlertDialog.Builder(context); | |
builder.setCancelable(false); | |
final AlertDialog alert = builder.create(); | |
alert.show(); | |
alert.setOnKeyListener(new DialogInterface.OnKeyListener() { | |
@Override | |
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { | |
if (keyCode == KeyEvent.KEYCODE_BACK | |
&& event.getRepeatCount() == 0) { | |
alert.dismiss(); | |
} | |
return true; | |
} | |
}); | |
alert.setContentView(R.layout.loading_layout); | |
return alert; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class DownloadService extends Service { | |
public static final String BUNDLE_KEY_DOWNLOAD_URL = "download_url"; | |
public static final String BUNDLE_KEY_TITLE = "title"; | |
private final String tag = "download"; | |
private static final int NOTIFY_ID = 0; | |
private int progress; | |
private NotificationManager mNotificationManager; | |
private boolean canceled; | |
private String downloadUrl; | |
private String mTitle = "正在下载%s"; | |
private String saveFileName = AppConfig.DEFAULT_SAVE_FILE_PATH; | |
private ICallbackResult callback; | |
private DownloadBinder binder; | |
private boolean serviceIsDestroy = false; | |
private Context mContext = this; | |
private Thread downLoadThread; | |
private Notification mNotification; | |
private Handler mHandler = new Handler() { | |
@Override | |
public void handleMessage(Message msg) { | |
// TODO Auto-generated method stub | |
super.handleMessage(msg); | |
switch (msg.what) { | |
case 0: | |
// 下载完毕 | |
mNotificationManager.cancel(NOTIFY_ID); | |
installApk(); | |
break; | |
case 2: | |
// 取消通知 | |
mNotificationManager.cancel(NOTIFY_ID); | |
break; | |
case 1: | |
int rate = msg.arg1; | |
if (rate < 100) { | |
RemoteViews contentview = mNotification.contentView; | |
contentview.setTextViewText(R.id.tv_download_state, mTitle + "(" + rate | |
+ "%" + ")"); | |
contentview.setProgressBar(R.id.pb_download, 100, rate, | |
false); | |
} else { | |
// 下载完毕后变换通知形式 | |
mNotification.flags = Notification.FLAG_AUTO_CANCEL; | |
mNotification.contentView = null; | |
Intent intent = new Intent(mContext, MainActivity.class); | |
// 告知已完成 | |
intent.putExtra("completed", "yes"); | |
// 更新参数,注意flags要使用FLAG_UPDATE_CURRENT | |
PendingIntent contentIntent = PendingIntent.getActivity( | |
mContext, 0, intent, | |
PendingIntent.FLAG_UPDATE_CURRENT); | |
// mNotification.setLatestEventInfo(mContext, "下载完成", | |
// "文件已下载完毕", contentIntent); | |
serviceIsDestroy = true; | |
stopSelf();// 停掉服务自身 | |
} | |
mNotificationManager.notify(NOTIFY_ID, mNotification); | |
break; | |
} | |
} | |
}; | |
@Override | |
public IBinder onBind(Intent intent) { | |
downloadUrl = intent.getStringExtra(BUNDLE_KEY_DOWNLOAD_URL); | |
saveFileName = saveFileName + getSaveFileName(downloadUrl); | |
mTitle = String.format(mTitle, intent.getStringExtra(BUNDLE_KEY_TITLE)); | |
return binder; | |
} | |
private String getSaveFileName(String downloadUrl) { | |
if (downloadUrl == null || StringUtils.isEmpty(downloadUrl)) { | |
return ""; | |
} | |
return downloadUrl.substring(downloadUrl.lastIndexOf("/")); | |
} | |
@Override | |
public void onCreate() { | |
super.onCreate(); | |
binder = new DownloadBinder(); | |
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); | |
stopForeground(true);// 这个不确定是否有作用 | |
} | |
private void startDownload() { | |
canceled = false; | |
downloadApk(); | |
} | |
/** | |
* 创建通知 | |
*/ | |
private void setUpNotification() { | |
int icon = R.mipmap.app_icon; | |
CharSequence tickerText = "准备下载"; | |
long when = System.currentTimeMillis(); | |
mNotification = new Notification(icon, tickerText, when); | |
// 放置在"正在运行"栏目中 | |
mNotification.flags = Notification.FLAG_ONGOING_EVENT; | |
RemoteViews contentView = new RemoteViews(getPackageName(), | |
R.layout.download_notification_show); | |
contentView.setTextViewText(R.id.tv_download_state, mTitle); | |
// 指定个性化视图 | |
mNotification.contentView = contentView; | |
Intent intent = new Intent(this, MainActivity.class); | |
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, | |
intent, PendingIntent.FLAG_UPDATE_CURRENT); | |
// 指定内容意图 | |
mNotification.contentIntent = contentIntent; | |
mNotificationManager.notify(NOTIFY_ID, mNotification); | |
} | |
private void downloadApk() { | |
downLoadThread = new Thread(mdownApkRunnable); | |
downLoadThread.start(); | |
} | |
/** | |
* 安装apk | |
*/ | |
private void installApk() { | |
File apkfile = new File(saveFileName); | |
if (!apkfile.exists()) { | |
return; | |
} | |
TDevice.installAPK(mContext, apkfile); | |
} | |
private Runnable mdownApkRunnable = new Runnable() { | |
@Override | |
public void run() { | |
File file = new File(AppConfig.DEFAULT_SAVE_FILE_PATH); | |
if (!file.exists()) { | |
file.mkdirs(); | |
} | |
String apkFile = saveFileName; | |
File saveFile = new File(apkFile); | |
try { | |
downloadUpdateFile(downloadUrl, saveFile); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
} | |
}; | |
public long downloadUpdateFile(String downloadUrl, File saveFile) | |
throws Exception { | |
int downloadCount = 0; | |
int currentSize = 0; | |
long totalSize = 0; | |
int updateTotalSize = 0; | |
HttpURLConnection httpConnection = null; | |
InputStream is = null; | |
FileOutputStream fos = null; | |
try { | |
URL url = new URL(downloadUrl); | |
httpConnection = (HttpURLConnection) url.openConnection(); | |
httpConnection | |
.setRequestProperty("User-Agent", "PacificHttpClient"); | |
if (currentSize > 0) { | |
httpConnection.setRequestProperty("RANGE", "bytes=" | |
+ currentSize + "-"); | |
} | |
httpConnection.setConnectTimeout(10000); | |
httpConnection.setReadTimeout(20000); | |
updateTotalSize = httpConnection.getContentLength(); | |
if (httpConnection.getResponseCode() == 404) { | |
throw new Exception("fail!"); | |
} | |
is = httpConnection.getInputStream(); | |
fos = new FileOutputStream(saveFile, false); | |
byte buffer[] = new byte[1024]; | |
int readsize = 0; | |
while ((readsize = is.read(buffer)) > 0) { | |
fos.write(buffer, 0, readsize); | |
totalSize += readsize; | |
// 为了防止频繁的通知导致应用吃紧,百分比增加10才通知一次 | |
if ((downloadCount == 0) | |
|| (int) (totalSize * 100 / updateTotalSize) - 4 > downloadCount) { | |
downloadCount += 4; | |
// 更新进度 | |
Message msg = mHandler.obtainMessage(); | |
msg.what = 1; | |
msg.arg1 = downloadCount; | |
mHandler.sendMessage(msg); | |
if (callback != null) | |
callback.OnBackResult(progress); | |
} | |
} | |
// 下载完成通知安装 | |
mHandler.sendEmptyMessage(0); | |
// 下载完了,cancelled也要设置 | |
canceled = true; | |
}catch (Exception e){ | |
e.printStackTrace(); | |
}finally { | |
if (httpConnection != null) { | |
httpConnection.disconnect(); | |
} | |
if (is != null) { | |
is.close(); | |
} | |
if (fos != null) { | |
fos.close(); | |
} | |
} | |
return totalSize; | |
} | |
public class DownloadBinder extends Binder { | |
public void start() { | |
if (downLoadThread == null || !downLoadThread.isAlive()) { | |
progress = 0; | |
setUpNotification(); | |
new Thread() { | |
public void run() { | |
// 下载 | |
startDownload(); | |
}; | |
}.start(); | |
} | |
} | |
public void cancel() { | |
canceled = true; | |
} | |
public int getProgress() { | |
return progress; | |
} | |
public boolean isCanceled() { | |
return canceled; | |
} | |
public boolean serviceIsDestroy() { | |
return serviceIsDestroy; | |
} | |
public void cancelNotification() { | |
mHandler.sendEmptyMessage(2); | |
} | |
public void addCallback(ICallbackResult callback) { | |
DownloadService.this.callback = callback; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static void openDownLoadService(Context mContext, String url, String versionName) { | |
final ICallbackResult callback = new ICallbackResult() { | |
@Override | |
public void OnBackResult(Object s) { | |
} | |
}; | |
ServiceConnection conn = new ServiceConnection() { | |
@Override | |
public void onServiceDisconnected(ComponentName name) { | |
} | |
@Override | |
public void onServiceConnected(ComponentName name, IBinder service) { | |
DownloadService.DownloadBinder binder = (DownloadService.DownloadBinder) service; | |
binder.addCallback(callback); | |
binder.start(); | |
} | |
}; | |
Intent intent = new Intent(mContext, DownloadService.class); | |
intent.putExtra(DownloadService.BUNDLE_KEY_DOWNLOAD_URL, url); | |
intent.putExtra(DownloadService.BUNDLE_KEY_TITLE, versionName); | |
mContext.startService(intent); | |
mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class UpdateUtils { | |
// Update Base Class | |
private AppBase mUpdate; | |
private Context mContext; | |
private boolean isShow = false; | |
private ProgressDialog _waitDialog; | |
private HttpCallBack mCheckUpdateHandle = new HttpCallBack() { | |
@Override | |
public void onSuccess(String t) { | |
super.onSuccess(t); | |
hideCheckDialog(); | |
try { | |
JSONObject response = new JSONObject(t); | |
ResultVO<AppBase> resultVO = new ResultVO<>(); | |
JsonUtils.toObjectObject(resultVO, response, AppBase.class); | |
if (resultVO.getRET_CODE().equals(ResponseCode.HM_SUCCESS)) { | |
mUpdate = resultVO.getRET_VO().get(0); | |
onFinshCheck(); | |
} else { | |
onFailure(0, null); | |
} | |
} catch (Exception e) { | |
} | |
} | |
@Override | |
public void onFailure(int errorNo, String strMsg) { | |
super.onFailure(errorNo, strMsg); | |
hideCheckDialog(); | |
if (isShow) { | |
showFaileDialog(); | |
} | |
} | |
// @Override | |
// public void onSuccess(int arg0, Header[] arg1, byte[] arg2) { | |
// hideCheckDialog(); | |
// mUpdate = XmlUtils.toBean(Update.class, | |
// new ByteArrayInputStream(arg2)); | |
// | |
// onFinshCheck(); | |
// } | |
}; | |
public UpdateUtils(Context context, boolean isShow) { | |
this.mContext = context; | |
this.isShow = isShow; | |
} | |
public boolean haveNew() { | |
if (this.mUpdate == null) { | |
return false; | |
} | |
boolean haveNew = false; | |
int curVersionCode = TDevice.getVersionCode(); | |
if (curVersionCode < Integer.parseInt(mUpdate.getVersionCode())) { | |
haveNew = true; | |
} | |
return haveNew; | |
} | |
public void checkUpdate() { | |
if (isShow) { | |
showCheckDialog(); | |
} | |
HttpConnUtils.checkUpdate(mContext, mCheckUpdateHandle); | |
} | |
private void onFinshCheck() { | |
if (haveNew()) { | |
showUpdateInfo(); | |
} else { | |
if (isShow) { | |
showLatestDialog(); | |
} | |
} | |
} | |
private void showCheckDialog() { | |
if (_waitDialog == null) { | |
_waitDialog = DialogHelp.getWaitDialog((Activity) mContext, "正在获取新版本信息..."); | |
} | |
_waitDialog.show(); | |
} | |
private void hideCheckDialog() { | |
if (_waitDialog != null) { | |
_waitDialog.dismiss(); | |
} | |
} | |
private void showUpdateInfo() { | |
if (mUpdate == null) { | |
return; | |
} | |
AlertDialog.Builder dialog = DialogHelp.getConfirmDialog(mContext, mUpdate.getIntroduction(), new DialogInterface.OnClickListener() { | |
@Override | |
public void onClick(DialogInterface dialogInterface, int i) { | |
UIHelper.openDownLoadService(mContext, mUpdate.getUrl(), mUpdate.getVersionName()); | |
} | |
}); | |
dialog.setTitle("发现新版本"); | |
dialog.show(); | |
} | |
private void showLatestDialog() { | |
DialogHelp.getMessageDialog(mContext, "已经是新版本了").show(); | |
} | |
private void showFaileDialog() { | |
DialogHelp.getMessageDialog(mContext, "网络异常,无法获取新版本信息").show(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment