/* * Copyright 2015 Hippo Seven * * 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.hippo.nimingban.client; import android.app.Activity; import android.app.NotificationManager; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.res.Resources; import android.net.Uri; import android.os.AsyncTask; import android.os.Build; import android.support.v7.app.AlertDialog; import android.support.v7.app.NotificationCompat; import android.widget.Toast; import com.hippo.network.DownloadClient; import com.hippo.network.DownloadRequest; import com.hippo.nimingban.NMBAppConfig; import com.hippo.nimingban.NMBApplication; import com.hippo.nimingban.R; import com.hippo.nimingban.client.data.DiscUrl; import com.hippo.nimingban.client.data.UpdateStatus; import com.hippo.nimingban.content.UpdateApkProvider; import com.hippo.nimingban.util.OpenUrlHelper; import com.hippo.nimingban.util.Settings; import com.hippo.text.Html; import com.hippo.unifile.UniFile; import com.hippo.util.TextUtils2; import com.hippo.util.Timer; import com.hippo.yorozuya.FileUtils; import java.io.File; import java.util.List; public final class UpdateHelper { private static boolean sUpdating = false; public static void showUpdateDialog(final Activity activity, final UpdateStatus status) { if (activity.isFinishing()) { return; } if (status == null) { return; } int versionCode = Settings.getVersionCode(); if (versionCode >= status.versionCode) { return; } if (status.info == null || status.versionName == null || status.size == 0) { return; } Resources resources = activity.getResources(); CharSequence message = TextUtils2.combine( resources.getString(R.string.version) + ": " + status.versionName + '\n' + resources.getString(R.string.size) + ": " + FileUtils.humanReadableByteCount(status.size, false) + "\n\n", Html.fromHtml(status.info)); new AlertDialog.Builder(activity) .setTitle(R.string.download_update) .setMessage(message) .setPositiveButton(R.string.download, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { downloadApk(activity, status.apkUrl, status.discUrl, status.failedUrl, "nimingban-" + status.versionName + ".apk"); } }) .show(); } public static void downloadApk(Context context, String url, List<DiscUrl> discUrls, String failedUrl, String filename) { if (sUpdating) { return; } sUpdating = true; context = context.getApplicationContext(); File dir = NMBAppConfig.getExternalAppDir(); if (dir == null) { Toast.makeText(context, R.string.download_update_failde, Toast.LENGTH_SHORT).show(); return; } DownloadRequest request = new DownloadRequest(); request.setUrl(url); request.setFilename(filename); request.setDir(UniFile.fromFile(dir)); request.setOkHttpClient(NMBApplication.getOkHttpClient(context)); new DownloadApkTask(context, request, Uri.fromFile(new File(dir, filename)), failedUrl).execute(); } private static class DownloadApkTask extends AsyncTask<Void, Void, Boolean> { private static final int NOTIFY_ID_DOWNLOADING = -1; private Context mContext; private DownloadRequest mRequest; private Uri mUri; private String mFailedUrl; private DownloadApkListener mListener; private final NotificationManager mNotifyManager; private NotificationCompat.Builder mDownloadingBuilder; private DownloadTimer mDownloadTimer; public DownloadApkTask(Context context, DownloadRequest request, Uri uri, String failedUrl) { mContext = context; mRequest = request; mFailedUrl = failedUrl; mListener = new DownloadApkListener(); mRequest.setListener(mListener); mNotifyManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); mDownloadingBuilder = new NotificationCompat.Builder(context); mDownloadingBuilder.setContentTitle(context.getString(R.string.downloading_update)) .setSmallIcon(android.R.drawable.stat_sys_download) .setOngoing(true) .setAutoCancel(false) .setProgress(0, 0, true); mNotifyManager.notify(NOTIFY_ID_DOWNLOADING, mDownloadingBuilder.build()); mDownloadTimer = new DownloadTimer(2000); mDownloadTimer.start(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // Only use content uri for Android N and above mUri = UpdateApkProvider.UPDATE_APK_URI; UpdateApkProvider.setUpdateApkFile(uri); } else { mUri = uri; } } @Override protected Boolean doInBackground(Void... params) { return DownloadClient.execute(mRequest); } @Override protected void onPostExecute(Boolean aBoolean) { if (aBoolean) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(mUri, "application/vnd.android.package-archive"); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivity(intent); } else { Toast.makeText(mContext, R.string.download_update_failde, Toast.LENGTH_SHORT).show(); if (mFailedUrl != null) { OpenUrlHelper.openUrl(mContext, mFailedUrl, false); } } sUpdating = false; mDownloadTimer.cancel(); mDownloadTimer = null; mListener = null; mNotifyManager.cancel(NOTIFY_ID_DOWNLOADING); mDownloadingBuilder = null; mRequest = null; mContext = null; } private class DownloadTimer extends Timer { private long mInterval; private long lastReceivedSize = 0; public DownloadTimer(long interval) { super(interval); mInterval = interval; } @Override public void onTick() { if (mDownloadingBuilder == null || mNotifyManager == null) { return; } long receivedSize = mListener.receivedSize; String speed = FileUtils.humanReadableByteCount((receivedSize - lastReceivedSize) * 1000 / mInterval, false) + "/s"; int progress = -1; long totalSize = mListener.totalSize; if (totalSize != -1l) { progress = (int) (receivedSize * 100 / totalSize); } lastReceivedSize = receivedSize; mDownloadingBuilder.setContentText(speed); if (progress == -1) { mDownloadingBuilder.setProgress(0, 0, true); } else { mDownloadingBuilder.setProgress(100, progress, false); } mNotifyManager.notify(NOTIFY_ID_DOWNLOADING, mDownloadingBuilder.build()); } @Override public void onCancel() { } } private class DownloadApkListener extends DownloadClient.SimpleDownloadListener { public long totalSize = -1l; public long receivedSize = 0l; @Override public void onConnect(long totalSize) { this.totalSize = totalSize; } @Override public void onDonwlad(long receivedSize, long singleReceivedSize) { this.receivedSize = receivedSize; } } } }