Last active
December 5, 2019 03:31
-
-
Save rayworks/69b8bb7720b46baa11ffb18b98161496 to your computer and use it in GitHub Desktop.
Foreground DownloadService
This file contains 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
import android.app.IntentService; | |
import android.app.Notification; | |
import android.app.NotificationChannel; | |
import android.app.NotificationManager; | |
import android.content.Intent; | |
import android.net.Uri; | |
import android.os.Build; | |
import android.os.Environment; | |
import android.support.annotation.NonNull; | |
import android.support.annotation.Nullable; | |
import android.support.v4.app.NotificationCompat; | |
import android.support.v4.content.FileProvider; | |
import java.io.BufferedOutputStream; | |
import java.io.File; | |
import java.io.FileOutputStream; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.util.concurrent.TimeUnit; | |
import okhttp3.OkHttpClient; | |
import okhttp3.Request; | |
import okhttp3.Response; | |
import timber.log.Timber; | |
import static android.os.Environment.DIRECTORY_DOWNLOADS; | |
// Usage : | |
// 1.Add the permission for foreground service | |
// <!-- OS 9.0+ --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> | |
// 2. register it on your manifest | |
public class FileDownloadService extends IntentService { | |
private final static String DOWNLOAD_CHANNEL_ID = "download_channel_id"; | |
private final static String DOWNLOAD_CHANNEL_NAME = "download_channel_name"; | |
private final static String DOWNLOAD_CHANNEL_DESC = "download_channel_desc"; | |
public static final String DOWNLOAD_URL = "download_url"; | |
private static final String AUTHORITY = BuildConfig.APPLICATION_ID + ".fileprovider"; | |
private String fileName; | |
public FileDownloadService() { | |
super("FileDownloadService"); | |
} | |
@Override | |
public void onDestroy() { | |
super.onDestroy(); | |
} | |
private void startInstall(@NonNull File file) { | |
Intent installIntent = new Intent(); | |
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { | |
installIntent.setAction(Intent.ACTION_VIEW); | |
installIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); | |
installIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); | |
// Timber.e(">>> InstallPermission granted : %b", isHasInstallPermissionWithO(context)); | |
Uri contentUri = FileProvider.getUriForFile(getApplicationContext(), AUTHORITY, file); | |
installIntent.setDataAndType(contentUri, "application/vnd.android.package-archive"); | |
} else { | |
installIntent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive"); | |
installIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); | |
} | |
// IPackageManager localIPackageManager = IPackageManager.Stub.asInterface(context.getPackageManager()); | |
try { | |
/*List<ResolveInfo> resolveInfos = getApplicationContext().getPackageManager().queryIntentActivities(installIntent, 0); | |
ResolveInfo target = null; | |
for (ResolveInfo ri : resolveInfos) { | |
ActivityInfo activityInfo = ri.activityInfo; | |
String activityName = activityInfo.name; | |
String pkg = activityInfo.packageName; | |
String appName = activityInfo.applicationInfo.name; | |
Timber.i(">>> filtered ResolveInfo: activity- %s | appName- %s | pkg - %s", activityName, appName, pkg); | |
if(pkg != null && pkg.endsWith("packageinstaller")) { | |
installIntent.setComponent(new ComponentName(pkg, activityName)); | |
break; | |
} | |
}*/ | |
Timber.w(">>> intent dumped : %s", installIntent); | |
// ResolveInfo: activity- com.android.packageinstaller.PackageInstallerActivity | appName- com.android.packageinstaller.InstallerApplication | pkg - com.miui.packageinstaller | |
startActivity(installIntent); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
} | |
@Override | |
protected void onHandleIntent(@Nullable Intent intent) { | |
if (intent != null) { | |
String downloadUrl = intent.getStringExtra(DOWNLOAD_URL); | |
File filesDir = Environment.getExternalStoragePublicDirectory(DIRECTORY_DOWNLOADS); //getApplicationContext().getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS); | |
if (filesDir == null) { | |
filesDir = getFilesDir(); | |
} else { | |
if (!filesDir.exists()) { | |
filesDir.mkdir(); | |
} | |
} | |
int sepPosition = downloadUrl.lastIndexOf("/"); | |
int endPosition = downloadUrl.lastIndexOf("."); | |
//Uri.fromFile("").getLastPathSegment(); | |
long millis = System.currentTimeMillis(); | |
fileName = downloadUrl.substring(sepPosition + 1, endPosition) + millis + downloadUrl.substring(endPosition); | |
File out = new File(filesDir, fileName); | |
Timber.w(">>> File will be put here : %s", out.getAbsolutePath()); | |
startForeground(0xEF, buildNotification()); | |
OkHttpClient client = new OkHttpClient.Builder() | |
.connectTimeout(30, TimeUnit.SECONDS) | |
.readTimeout(30, TimeUnit.SECONDS) | |
.build(); | |
Request request = new Request.Builder().url(downloadUrl).get().build(); | |
InputStream in = null; | |
BufferedOutputStream bos = null; | |
try { | |
Response response = client.newCall(request).execute(); | |
if (response.code() == 200) { | |
in = response.body().byteStream(); | |
FileOutputStream fos = new FileOutputStream(out); | |
bos = new BufferedOutputStream(fos); | |
byte[] buffer = new byte[8192]; | |
int len = 0; | |
while ((len = in.read(buffer)) >= 0) { | |
bos.write(buffer, 0, len); | |
} | |
bos.flush(); | |
Timber.i(">>> download completed!"); | |
startInstall(out); | |
} else { | |
Timber.i(">>> download error: %s", response.message()); | |
} | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} finally { | |
IOUtils.closeSilently(bos); | |
IOUtils.closeSilently(in); | |
try { | |
Thread.sleep(50000); | |
stopForeground(true); | |
stopSelf(); | |
} catch (InterruptedException e) { | |
e.printStackTrace(); | |
} | |
} | |
} | |
} | |
private Notification buildNotification() { | |
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { | |
int importance = NotificationManager.IMPORTANCE_DEFAULT; | |
NotificationChannel channel = new NotificationChannel(DOWNLOAD_CHANNEL_ID, DOWNLOAD_CHANNEL_NAME, importance); | |
channel.setDescription(DOWNLOAD_CHANNEL_DESC); | |
NotificationManager notificationManager = getSystemService(NotificationManager.class); | |
notificationManager.createNotificationChannel(channel); | |
} | |
NotificationCompat.Builder b = new NotificationCompat.Builder(this, DOWNLOAD_CHANNEL_ID); | |
b.setOngoing(true) | |
.setContentText(fileName) | |
.setSmallIcon(android.R.drawable.stat_sys_download) | |
.setTicker("Downloading...") | |
.setPriority(NotificationCompat.PRIORITY_DEFAULT) | |
.setAutoCancel(true); | |
return b.build(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment