com.linroid.pushapp.service.DownloadService.java Source code

Java tutorial

Introduction

Here is the source code for com.linroid.pushapp.service.DownloadService.java

Source

/*
 * 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());
    }
}