Java tutorial
/* * Copyright (c) linroid 2015. * * 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.linroid.pushapp.service; import android.app.KeyguardManager; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.database.Cursor; import android.net.Uri; import android.os.IBinder; import android.os.PowerManager; import android.support.v4.app.NotificationCompat; import android.text.TextUtils; import android.widget.Toast; import com.linroid.pushapp.App; import com.linroid.pushapp.Constants; import com.linroid.pushapp.R; import com.linroid.pushapp.model.Pack; import com.linroid.pushapp.module.identifier.PackageDownloadDir; import com.linroid.pushapp.util.AndroidUtil; import com.linroid.pushapp.util.BooleanPreference; import com.linroid.pushapp.util.IntentUtil; import com.linroid.pushapp.util.MD5; import com.linroid.pushapp.util.StringPreference; import com.squareup.sqlbrite.BriteDatabase; import com.thin.downloadmanager.DownloadRequest; import com.thin.downloadmanager.DownloadStatusListener; import com.thin.downloadmanager.ThinDownloadManager; import java.io.File; import java.util.HashMap; import java.util.Map; import javax.inject.Inject; import javax.inject.Named; import hugo.weaving.DebugLog; import timber.log.Timber; public class DownloadService extends Service { public static final String EXTRA_PACKAGE = "package"; public static final int NOTIFICATION_DOWNLOAD = 0x111; @Inject NotificationManager notificationManager; @Named(Constants.SP_TOKEN) @Inject StringPreference token; @Named(Constants.SP_AUTO_INSTALL) @Inject BooleanPreference autoInstall; @PackageDownloadDir @Inject File downloadDir; @Inject SharedPreferences preferences; @Inject BriteDatabase db; private ThinDownloadManager downloadManager; private Map<Integer, Pack> downloadPackageMap; public static Intent createNewDownloadIntent(Context context, Pack pack) { Intent intent = new Intent(context, DownloadService.class); intent.putExtra(DownloadService.EXTRA_PACKAGE, pack); return intent; } @Override public void onCreate() { super.onCreate(); App.from(this).component().inject(this); downloadManager = new ThinDownloadManager(); downloadPackageMap = new HashMap<>(); } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } @DebugLog @Override public int onStartCommand(Intent intent, int flags, int startId) { if (intent == null || !intent.hasExtra(EXTRA_PACKAGE)) { // throw new IllegalArgumentException("require push info extra"); Timber.e("require package info extra"); return super.onStartCommand(intent, flags, startId); } Timber.d("Bundle: %s", AndroidUtil.sprintBundle(intent.getExtras())); Pack pack = intent.getParcelableExtra(EXTRA_PACKAGE); newDownloadTask(pack); return super.onStartCommand(intent, flags, startId); } private void newDownloadTask(Pack pack) { if (pack == null || TextUtils.isEmpty(pack.getDownloadUrl())) { Timber.e("invalid package download url"); return; } Timber.d("Download url: %s", pack.getDownloadUrl()); Uri downloadUri = Uri.parse(pack.getDownloadUrl()); File savedDir = new File(downloadDir, String.valueOf(pack.getId())); File savedFile = new File(savedDir, downloadUri.getLastPathSegment()); DownloadRequest request = new DownloadRequest(downloadUri); if (downloadPackageMap.containsKey(pack.getId())) { Timber.w("download existing... break out"); return; } if (!savedDir.exists()) { savedDir.mkdir(); } //??? Cursor cursor = db.query(Pack.DB.SQL_ITEM_QUERY, String.valueOf(pack.getId())); if (cursor.moveToNext()) { Pack saved = Pack.fromCursor(cursor); if (!TextUtils.isEmpty(saved.getPath()) && savedFile.exists()) { onDownloadComplete(saved); return; } } else { db.insert(Pack.DB.TABLE_NAME, pack.toContentValues()); } pack.setPath(savedFile.getAbsolutePath()); request.setDestinationURI(Uri.fromFile(savedFile)); request.setDownloadListener(new DownloadStatusListener() { @Override @DebugLog public void onDownloadComplete(int i) { prevProgress = -1; Pack pack = downloadPackageMap.remove(i); CharSequence label = AndroidUtil.getApkLabel(DownloadService.this, pack.getPath()); pack.setAppName(label != null ? label.toString() : pack.getAppName()); //TODO ThinDownloadManagerAPK?MD5?) String md5 = MD5.calculateFile(new File(pack.getPath())); pack.setMD5(md5); db.update(Pack.DB.TABLE_NAME, pack.toContentValues(), Pack.DB.WHERE_ID, String.valueOf(pack.getId())); DownloadService.this.onDownloadComplete(pack); } @Override @DebugLog public void onDownloadFailed(int i, int i1, String s) { Pack pack = downloadPackageMap.get(i); Timber.e("%s :( %d %s", pack.getAppName(), i1, s); showNotification(pack, -1); downloadPackageMap.remove(i); prevProgress = -1; } @Override public void onProgress(int i, long l, int i1) { showNotification(downloadPackageMap.get(i), i1); } }); int downloadId = downloadManager.add(request); downloadPackageMap.put(downloadId, pack); showNotification(pack, 0); } /** * ? * @param pack */ private void onDownloadComplete(Pack pack) { Timber.d("%s ?,?:%s", pack.getAppName(), pack.getPath()); int toastResId = R.string.toast_download_complete; if (autoInstall.getValue()) { startActivity(IntentUtil.installApk(pack.getPath())); if (AndroidUtil.isAccessibilitySettingsOn(this, ApkAutoInstallService.class.getCanonicalName())) { PowerManager powermanager = ((PowerManager) getSystemService(Context.POWER_SERVICE)); PowerManager.WakeLock wakeLock = powermanager.newWakeLock((PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), "Install Worker, FULL WAKE LOCK"); wakeLock.acquire(); wakeLock.release(); KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE); // if(keyguardManager.isDeviceLocked()) { final KeyguardManager.KeyguardLock keyguardLock = keyguardManager.newKeyguardLock("unLock"); keyguardLock.disableKeyguard(); // } ApkAutoInstallService.addInstallPackage(pack); toastResId = R.string.toast_start_install; } else { toastResId = R.string.toast_download_complete; } } Toast.makeText(this, getString(toastResId, pack.getAppName()), Toast.LENGTH_SHORT).show(); } /** * */ int prevProgress = -1; private void showNotification(Pack pack, int progress) { if (pack == null) { return; } if (prevProgress == progress) { return; } prevProgress = progress; String contentText; if (progress == 100) { contentText = getString(R.string.msg_download_complete); } else if (progress < 0) { contentText = getString(R.string.msg_download_failed); Toast.makeText(this, getString(R.string.toast_download_failed, pack.getAppName()), Toast.LENGTH_SHORT) .show(); } else { if (progress == 0) { Toast.makeText(this, getString(R.string.toast_start_download, pack.getAppName()), Toast.LENGTH_LONG) .show(); } contentText = getString(R.string.msg_downloading); } NotificationCompat.Builder builder = new NotificationCompat.Builder(this) .setContentTitle( getString(R.string.msg_download_title, pack.getAppName(), "v" + pack.getVersionName())) .setSmallIcon(R.mipmap.ic_launcher).setAutoCancel(false).setContentText(contentText); if (progress > 0) { builder.setProgress(100, Math.max(progress, 0), false) .setContentInfo(getString(R.string.msg_download_progress, progress)); } else if (progress == 0) { builder.setProgress(100, 0, true); } if (progress == 100) { builder.setSmallIcon(R.drawable.ic_stat_complete); Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(new File(pack.getPath())), "application/vnd.android.package-archive"); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); PendingIntent pi = PendingIntent.getActivity(this, 0x1, intent, 0); builder.setContentIntent(pi); } // ImageRequest request = ImageRequest.fromUri(pack.getIconUrl()); // ImagePipeline pipeline = Fresco.getImagePipeline(); // pipeline.prefetchToDiskCache(request, this); notificationManager.notify(pack.getId(), builder.build()); } }