Android: Unable to update custom notification when I kill my app - android

I am downloading multiple files one after the other in service. I want to update download progress in notification. But my notification doesn't update when I kill my app. Download works on different thread. Download works fine in when app is running. When I kill app from recent section, I am unable to update notification.
Here is my DownloadService class
public class DownloadService extends Service {
public static DownloadMap<String, Downloadables> map = new DownloadMap<String, Downloadables>();
private static Thread thread;
private DownloadCancelReceiver receiver;
public DownloadService() {
}
public class BackgroundThread extends Thread {
int serviceId;
private DownloadMap<String, Downloadables> map;
private SpeedRevisionDatabase helper;
private final int notificationId = 1;
private RemoteViews remoteViewsSmall, remoteViewsBig;
private NotificationManagerCompat notificationManager;
private NotificationCompat.Builder mBuilder, mBuilderComplete, downloadFailBuilder;
public BackgroundThread(int serviceId, DownloadMap<String, Downloadables> map) {
this.serviceId = serviceId;
this.map = new DownloadMap<>();
this.map.putAll(map);
}
#Override
public void run() {
remoteViewsSmall = new RemoteViews(getApplicationContext().getPackageName(), R.layout.download_notification_small);
remoteViewsBig = new RemoteViews(getApplicationContext().getPackageName(), R.layout.download_notification);
Intent cancelDownload = new Intent("CANCEL_DOWNLOAD");
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 100, cancelDownload, 0);
remoteViewsBig.setOnClickPendingIntent(R.id.tvCancel, pendingIntent);
notificationManager = NotificationManagerCompat.from(DownloadService.this);
mBuilder = new NotificationCompat.Builder(DownloadService.this, "default");
initChannels(DownloadService.this);
mBuilder.setContentTitle("Download is in progress")
.setContentText("Please wait...")
.setSmallIcon(R.mipmap.download)
.setOngoing(true)
.setCustomContentView(remoteViewsSmall)
.setCustomBigContentView(remoteViewsBig)
.setPriority(NotificationCompat.PRIORITY_HIGH);
notificationManager.notify(notificationId, mBuilder.build());
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
try {
String path = getApplicationContext().getApplicationInfo().dataDir + "/" + "UEP";
File uepFolder = new File(path);
if (!uepFolder.exists()) {
uepFolder.mkdir();
}
int i = 0;
while (map.entrySet().iterator().hasNext()) {
Log.e("WhileCheck", "Now i is " + i);
Map.Entry data = (Map.Entry) map.entrySet().iterator().next();
try {
Downloadables download = (Downloadables) data.getValue();
if (NetworkUtil.getConnectivityStatus(getApplicationContext()) == 0) {
throw new InternetDisconnectedException("Internet Disconnected");
}
HttpURLConnection urlConnection;
InputStream inputStream;
//finding file on internet
try {
URL url = new URL(download.URL);
if (url.toString().endsWith(".xps")) {
url = new URL(url.toString().replace(".xps", ".pdf"));
}
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.connect();
inputStream = urlConnection.getInputStream();
} catch (IOException e) {
Log.e("IOException", "" + e.getMessage());
i++;
map.remove(data.getKey());
notificationManager.notify(notificationId, mBuilder.build());
continue;
}
//Downloading file over internet
File file = new File(uepFolder + "/" + download.FileName + "" + download.Format + ".download");
try {
int fileSize = urlConnection.getContentLength();
FileOutputStream fileOutput = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int bufferLength = 0;
int count = 0;
int previousProgress = 0;
while ((bufferLength = inputStream.read(buffer)) > 0) {
if (this.isInterrupted()) {
throw new InterruptedException("Thread has been kill (Destroyed)");
}
fileOutput.write(buffer, 0, bufferLength);
count += bufferLength;
int progress = (int) (count * 100L / (float) fileSize);
if (previousProgress > 999) {
updateProgress(map.insertedCount, i, progress, download.Name);
notificationManager.notify(notificationId, mBuilder.build());
previousProgress = 0;
}
previousProgress++;
}
fileOutput.close();
} catch (IOException e) {
Log.e("IOException", "" + e.getMessage());
i++;
map.remove(data.getKey());
continue;
}
File actualFile = new File(uepFolder + "/" + download.FileName + "" + download.Format);
file.renameTo(actualFile);
Log.e("Downloaded",""+actualFile.getAbsoluteFile());
} catch (InterruptedException | InternetDisconnectedException e) {
throw e;
}
i++;
map.remove(data.getKey());
Log.e("Downloaded", "Remaining files are "+map.size());
}
Log.e("WhileCheck", "While End");
// Due to thread, sometime the sequence of code flow is not in correct flow, and "Download complete" Notifaction is getting shown
// Hence this check is required.
if (this.isInterrupted()) {
throw new InterruptedException("Thread has been kill (Destroyed)");
}
notificationManager.cancel(notificationId);
mBuilderComplete = new NotificationCompat.Builder(DownloadService.this, "default");
initChannels(DownloadService.this);
mBuilderComplete.setOngoing(false)
.setContentTitle("Download Complete")
.setColor(Color.WHITE)
.setSmallIcon(R.drawable.download);
notificationManager.notify(2, mBuilderComplete.build());
Log.e("DownloadingService", "File downloaded successfully");
stopSelf();
map.insertedCount = 0;
} catch (InterruptedException e) {
closeNotification();
Log.e("InterruptedException", "" + e.getMessage());
} catch (InternetDisconnectedException e) {
stopSelf();
closeNotification();
showNotification("Internet disconnected", "Download failed. Try again later.");
Log.e("InternetDisconnect", "" + e.getMessage());
}
}
private void updateProgress(int totalFiles, int currentFileCount, int currentProgress, String fileName) {
remoteViewsSmall.setTextViewText(R.id.tvOverAll, currentFileCount + "/" + totalFiles);
remoteViewsSmall.setProgressBar(R.id.overallProgress, totalFiles, currentFileCount, false);
remoteViewsBig.setTextViewText(R.id.tvOverAll, currentFileCount + "/" + totalFiles);
remoteViewsBig.setTextViewText(R.id.tvFileName, "Downloading " + fileName);
remoteViewsBig.setTextViewText(R.id.tvCurrentProgress, currentProgress + "%");
remoteViewsBig.setProgressBar(R.id.overallProgress, totalFiles, currentFileCount, false);
remoteViewsBig.setProgressBar(R.id.currentProgress, 100, currentProgress, false);
}
public void closeNotification() {
if (notificationManager != null)
notificationManager.cancel(notificationId);
}
public void showNotification(String title, String message) {
downloadFailBuilder = new NotificationCompat.Builder(DownloadService.this, "default");
initChannels(DownloadService.this);
downloadFailBuilder.setOngoing(false)
.setContentTitle(title)
.setContentText(message)
.setColor(Color.WHITE)
.setSmallIcon(android.R.drawable.stat_sys_warning);
notificationManager.notify(3, downloadFailBuilder.build());
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null) {
ArrayList<Downloadables> list = (ArrayList<Downloadables>) intent.getSerializableExtra("downloadList");
for (Downloadables d : list) {
String key = d.Name + "" + d.FileName;
map.put(key, d);
}
if (thread == null || !thread.isAlive()) {
thread = new BackgroundThread(startId, map);
receiver = new DownloadCancelReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
intentFilter.addAction("CANCEL_DOWNLOAD");
registerReceiver(receiver, intentFilter);
thread.start();
}
}
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
Log.e("Service", " Stop");
try {
thread.interrupt();
} catch (Exception e) {
Log.e("Exception", "" + e.getMessage());
}
map.clear();
unregisterReceiver(receiver);
//closeNotification();
}
public static class DownloadCancelReceiver extends BroadcastReceiver {
public DownloadCancelReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equalsIgnoreCase("CANCEL_DOWNLOAD")) {
Intent intent1 = new Intent(context, DownloadService.class);
context.stopService(intent1);
}
}
}
public void initChannels(Context context) {
if (Build.VERSION.SDK_INT < 26) {
return;
}
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel channel = new NotificationChannel("default", "Channel name", NotificationManager.IMPORTANCE_LOW);
channel.setDescription("Channel description");
channel.setImportance(NotificationManager.IMPORTANCE_LOW);
channel.setSound(null, null);
notificationManager.createNotificationChannel(channel);
}
private class InternetDisconnectedException extends Exception {
public InternetDisconnectedException(String message) {
super(message);
}
}
public static class DownloadMap<String, Downloadables> extends HashMap<String, Downloadables> {
public int insertedCount;
#Override
public Downloadables put(String key, Downloadables value) {
insertedCount++;
return super.put(key, value);
}
}
}
And From activity I start service like this.
ArrayList<Downloadables> list = helper.GetVideoFileList();
Intent intent1 = new Intent(SRDownloadActivity.this, DownloadService.class);
intent1.putExtra("downloadList", list);
startService(intent1);
I can even Add files to HashMap while downloading is in progress. It also worked fine.
I am unable to figure it out why it is not running in background since it is on different thread.
Here is my notification look like

Threads are killed by the Android OS even if the main app is still working and they dont have access to the UI thats why u should use AsyncTask class its a like a thread that works in background but it has access to the UI of the main. And the jobdispatcher class can help u assign jobs in the background
Here is a good tutorial https://youtu.be/das7FmQIGik

Related

Update progress of notification from a background service

I'm trying to update the progress of a notification during ftp upload handled by a background service, I tried directly from the service and after using a ResultReceiver but when the upload starts, the notification menu is freezed until the upload is done.How can I do this?
FtpService
public class FtpService extends IntentService {
public static final int UPDATE_PROGRESS = 10;
// IntentService can perform, e.g. ACTION_FETCH_NEW_ITEMS
private static final String ACTION_SEND = "SEND";
private static final String EXTRA_PATH = "PATH";
private static final String PREFERENCES = "virtualtv";
private SharedPreferences mPrefs;
private NotificationManager mNotifyManager;
private NotificationCompat.Builder mBuilder;
/********* work only for Dedicated IP ***********/
private String FTP_HOST= "";
/********* FTP USERNAME ***********/
private String FTP_USER;
/********* FTP PASSWORD ***********/
private String FTP_PASS;
private String FTP_PORT;
private String PATH;
private Context mContext;
public FTPClient ftpClient;
private ResultReceiver mUploadReceiver;
public FtpService() {
super("FtpService");
}
/**
* Starts this service to perform action Foo with the given parameters. If
* the service is already performing a task this action will be queued.
*
* #see IntentService
*/
// TODO: Customize helper method
public static void startActionSend(Context context, String param1) {
Intent intent = new Intent(context, FtpService.class);
intent.setAction(ACTION_SEND);
intent.putExtra(EXTRA_PATH, param1);
intent.putExtra("UPLOAD_RECEIVER", new UploadReceiver(new Handler(), context));
context.startService(intent);
}
#Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
mContext = this;
final String action = intent.getAction();
mUploadReceiver = intent.getParcelableExtra("UPLOAD_RECEIVER");
if (ACTION_SEND.equals(action)) {
final String filePath = intent.getStringExtra(EXTRA_PATH);
mPrefs = mContext.getSharedPreferences(PREFERENCES, Context.MODE_PRIVATE);
JsonObject config = Account.getInstance(mContext).getConfig();
if(mPrefs != null && config != null){
FTP_HOST = config.get("ftp_host").getAsString();
FTP_USER = config.get("ftp_username").getAsString();
FTP_PASS = config.get("ftp_password").getAsString();
FTP_PORT = config.get("ftp_port").getAsString();
PATH = config.get("ftp_path").getAsString();
}
handleActionSend(filePath);
}
}
}
/**
* Handle action Foo in the provided background thread with the provided
* parameters.
*/
private void handleActionSend(String filePath) {
File f = new File(filePath);
uploadFile(f);
}
public boolean uploadFile(final File f){
try {
ftpClient = new FTPClient();
ftpClient.connect(FTP_HOST, Integer.valueOf(FTP_PORT));
boolean b = ftpClient.login(FTP_USER, FTP_PASS);
Log.d("Login", "" + b);
b = ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
Log.d("file_type", "" + b);
b = ftpClient.changeWorkingDirectory(PATH);
Log.d("directory", "" + b);
// ftpClient.setFileTransferMode(FTP.BINARY_FILE_TYPE);
//
int reply = ftpClient.getReplyCode();
Log.d("reply", "" + reply);
// if(!FTPReply.isPositiveCompletion(reply)) {
// ftpClient.logout();
// ftpClient.disconnect();
// Log.d("ftp", "FTP server refused connection.");
// return false;
// }
InputStream srcFileStream = new FileInputStream(f);
// BufferedInputStream buffIn = new BufferedInputStream(new FileInputStream(f));
ftpClient.setControlKeepAliveTimeout(10);
ftpClient.enterLocalPassiveMode();
final int fileSize = (int) (FileUtils.sizeOf(f) / 1024);
// dati trasferiti
ftpClient.setCopyStreamListener(new CopyStreamListener() {
#Override
public void bytesTransferred(CopyStreamEvent event) {
}
#Override
public void bytesTransferred(long totalBytesTransferred, int bytesTransferred, long streamSize) {
Log.d("ftp", "total:" + totalBytesTransferred / 1024 + " trasnferred: " + bytesTransferred + " size:" + fileSize);
Bundle data = new Bundle();
data.putInt("fileSize", fileSize);
data.putInt("kbyte_transferred", (int) totalBytesTransferred / 1024);
mUploadReceiver.send(UPDATE_PROGRESS, data);
}
});
// Log.d("buffer", "" + buffIn.available());
Log.d("ftp", "storing file...");
boolean result = ftpClient.storeFile(f.getName(), srcFileStream);
Log.d("ftp", "result:" + result);
Log.d("ftp", "reply code:" + ftpClient.getReplyCode());
// inputStream.close();
srcFileStream.close();
// buffIn.close();
ftpClient.logout();
ftpClient.disconnect();
return result;
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (CopyStreamException e) {
e.printStackTrace();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if(ftpClient.isConnected()) {
try {
ftpClient.disconnect();
} catch(IOException ioe) {
ioe.printStackTrace();
}
}
}
return false;
}
}
UploadReceiver
class UploadReceiver extends ResultReceiver{
private NotificationManager mNotifyManager;
private NotificationCompat.Builder mBuilder;
private int id = 1;
public UploadReceiver(Handler handler, Context context) {
super(handler);
final int id = 1;
//Gestione notifica
mNotifyManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(context);
mBuilder.setContentTitle("Picture Download")
.setContentText("Download in progress")
.setSmallIcon(R.drawable.ic_launcher);
}
#Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
super.onReceiveResult(resultCode, resultData);
if (resultCode == FtpService.UPDATE_PROGRESS) {
int fileSize = resultData.getInt("file_size");
int transferred = resultData.getInt("kbyte_transferred");
mBuilder.setProgress(fileSize,transferred, false);
mNotifyManager.notify(id, mBuilder.build());
}
}
}
I solved the issue adding a check with an interval of 1000 milliseconds, if these have gone the UploadReceiver can update the notify and in this way it seems to work fine without freeze.It works also with a lower interval as 500 milliseconds.
Guys is my case these many times progress is rendering but I want only 100 times of progress so this code solve my issue.
Put int oldProgress =1;
int progresss = (int) ((progress.currentBytes / (float) progress.totalBytes) * 100);
if(progresss>oldProgress)
{
oldProgress=progresss;
notificationBuilder.setProgress(100, progresss,false);
notification = notificationBuilder.build();
notificationManager.notify(notificationID,notification);
}

Repeatedly Download File on background Service

This is my code. When i click download button, it download twice. How to stop second time downloading? Please help me to prevent second time downloading.
this my button click listener:
downloadPackage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
downloadPackage.setEnabled(false);
SharedPreferences.Editor editor = getSharedPreferences("SETID", MODE_PRIVATE).edit();
editor.putInt("setId", setId);
editor.commit();
Intent intent = new Intent(ReadingListeningTestActivity.this, DownloadService.class);
startService(intent);
}
});
this is my
Download Service:
public class DownloadService extends Service {
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
private NotificationManager notificationManager;
private NotificationCompat.Builder notificationBuilder;
private int totalFileSize;
SharedPreferences prefs;
private boolean isDownloading = false;
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
prefs = getSharedPreferences("SETID", MODE_PRIVATE);
int setId = prefs.getInt("setId", 0);
Log.d("SEtID", setId + "");
if (isDownloading) {
return;
} else {
Log.d("Download", "isDownloading: " + isDownloading);
isDownloading = true;
initDownload(setId);
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
private void initDownload(int setId) {
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... voids) {
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationBuilder = new NotificationCompat.Builder(getApplicationContext())
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(data.getTitle())
.setContentText("Downloading File")
.setAutoCancel(true);
notificationManager.notify(0, notificationBuilder.build());
downloadFileTest("test.zip");
return null;
}
}.execute();
}
private void downloadFileTest(String uri) {
int count;
InputStream stream = null;
OutputStream output = null;
HttpURLConnection connection = null;
String fileName = packageName(uri);
try {
URL url = new URL(Application.BASE_URL + uri);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
return;
}
byte data[] = new byte[4096];
long fileSize = connection.getContentLength();
stream = new BufferedInputStream(connection.getInputStream());
File outputFile = getCacheDir(fileName + ".part");
output = new FileOutputStream(outputFile);
try {
long total = 0;
long startTime = System.currentTimeMillis();
int timeCount = 1;
while ((count = stream.read(data)) != -1) {
total += count;
totalFileSize = (int) (fileSize / (Math.pow(1024, 2)));
double current = Math.round(total / (Math.pow(1021, 2)));
int progress = (int) ((total * 100) / fileSize);
long currentTime = System.currentTimeMillis() - startTime;
Download download = new Download();
download.setTotalFileSize(totalFileSize);
if (currentTime > 1000 * timeCount) {
download.setCurrentFileSize((int) current);
download.setProgress(progress);
sendNotification(download);
timeCount++;
}
output.write(data, 0, count);
}
} catch (IOException e) {
isDownloading = false;
prefs.edit().clear().commit();
outputFile.delete();
onErrorDownload("Internet Connection Problem Retry Download");
} finally {
isDownloading = false;
prefs.edit().clear().commit();
File originalName = getCacheDir(fileName);
if (originalName.exists()) {
outputFile.delete();
throw new IOException("file exists");
}
boolean success = outputFile.renameTo(originalName);
if (success) {
if (connection != null)
connection.disconnect();
onDownloadComplete();
output.flush();
output.close();
stream.close();
}
}
} catch (IOException e) {
isDownloading = false;
prefs.edit().clear().commit();
Log.d("Test", "Main");
if (e.getMessage().equals("file exists"))
onErrorDownload("Package Already Exists");
else
onErrorDownload("Internet Connection Problem Retry Download");
}
}
private void onDownloadComplete() {
Download download = new Download();
download.setProgress(100);
sendIntent(download);
notificationManager.cancel(0);
notificationBuilder.setOngoing(false);
notificationBuilder.setProgress(0, 0, false);
notificationBuilder.setContentText("File Downloaded");
notificationManager.notify(0, notificationBuilder.build());
}
private void onErrorDownload(String message) {
Download download = new Download();
download.setProgress(download.getProgress());
sendIntent(download);
notificationManager.cancel(0);
notificationBuilder.setOngoing(false);
notificationBuilder.setProgress(0, 0, false);
notificationBuilder.setContentText(message);
notificationManager.notify(0, notificationBuilder.build());
}
private void sendNotification(Download download) {
sendIntent(download);
notificationBuilder.setProgress(100, download.getProgress(), false);
notificationBuilder.setOngoing(true);
notificationBuilder.setContentText("Downloading Progress " + download.getProgress() + "%" + " /100%");
notificationManager.notify(0, notificationBuilder.build());
}
private void sendIntent(Download download) {
Intent intent = new Intent(ReadingListeningTestActivity.MESSAGE_PROGRESS);
intent.putExtra("download", download);
LocalBroadcastManager.getInstance(DownloadService.this).sendBroadcast(intent);
}
private String packageName(String uri) {
String[] parts = uri.split("/");
return parts[parts.length - 1];
}
public File getCacheDir(String packageName) {
File cache = null;
File external = getApplication().getExternalCacheDir();
if (external != null && external.exists()) {
cache = external;
} else {
cache = getApplication().getCacheDir();
}
File file = new File(cache, packageName);
return file;
}
}

Manage Queue in android with service

I have a activity with recycler-view, and each list item has a download button.inside button click event i manage make call for download-service.so how can i manage queue when user click more than one download button with custom notification update.
I have googled and tried some solutions are:
1.How to Manage Queue of Runnable Tasks in Android
2.how to handle a queue in android?? java
3.Best way to update Activity from a Queue
but doesn't find the correct way to implement queue with notification update.
Here is my DownloadService Code:
public class DownloadApkService extends Service {
private NotificationCompat.Builder notificationBuilder;
private NotificationManager notificationManager;
String downloadLocation;
String appId = null;
String appLink = null;
String appName = null;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("Queue", "queue");
appId = intent.getStringExtra(Constants.COM_APP_ID);
appLink = intent.getStringExtra(Constants.COM_APP_LINK);
appName = intent.getStringExtra(Constants.COM_APP_NAME);
Thread thread=new Thread(new MyThread(startId));
thread.start();
return START_STICKY;
}
final class MyThread implements Runnable {
int service_id;
MyThread(int service_id) {
this.service_id = service_id;
}
#Override
public void run() {
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationBuilder = new NotificationCompat.Builder(DownloadApkService.this)
.setSmallIcon(R.drawable.ic_list_app_icon)
.setContentTitle(appName).setProgress(0, 0, true)
.setContentText("Downloading APK")
.setOngoing(true)
.setAutoCancel(true);
notificationManager.notify(0, notificationBuilder.build());
downloadApk();
}
}
private void downloadApk() {
downloadLocation = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/";
String fileName = appName + ".apk";
downloadLocation += fileName;
File sourceFile = new File(downloadLocation);
if (sourceFile.exists()) {
sourceFile.delete();
}
Intent intentResponse = new Intent();
intentResponse.setAction(Constants.ACTION_DOWNLOADING_APK);
intentResponse.putExtra(Constants.COM_APP_ID, appId);
intentResponse.putExtra(Constants.COM_APK_DOWNLOAD_PERCENTAGE, "0");
sendBroadcast(intentResponse);
new DownloadFileFromURL().execute(appLink);
}
public void installApk(Uri uri) {
Intent install = new Intent(Intent.ACTION_VIEW);
install.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
install.setDataAndType(uri,
"application/vnd.android.package-archive");
DownloadApkService.this.startActivity(install);
}
/**
* Background Async Task to download file
*/
class DownloadFileFromURL extends AsyncTask<String, String, String> {
/**
* Before starting background thread Show Progress Bar Dialog
*/
#Override
protected void onPreExecute() {
super.onPreExecute();
}
/**
* Downloading file in background thread
*/
#Override
protected String doInBackground(String... f_url) {
int count;
try {
Log.e("ULR", f_url[0]);
URL url = new URL(f_url[0].trim());
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.connect();
// this will be useful so that you can show a tipical 0-100%
// progress bar
int lenghtOfFile = connection.getContentLength();
Log.e("Length", lenghtOfFile + "");
// download the file
InputStream input = connection.getInputStream();
downloadLocation = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/";
String fileName = appName + ".apk";
downloadLocation += fileName;
// Output stream
FileOutputStream output = new FileOutputStream(downloadLocation);
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
// publishing the progress....
// After this onProgressUpdate will be called
publishProgress("" + (int) ((total * 100) / lenghtOfFile));
// writing data to file
output.write(data, 0, count);
}
// flushing output
output.flush();
// closing streams
output.close();
input.close();
} catch (Exception e) {
Log.e("Error: ", e.getStackTrace().toString());
}
return null;
}
/**
* Updating progress bar
*/
protected void onProgressUpdate(String... progress) {
// setting progress percentage
Intent intentResponse = new Intent();
intentResponse.setAction(Constants.ACTION_DOWNLOADING_APK);
intentResponse.putExtra(Constants.COM_APP_ID, appId);
intentResponse.putExtra(Constants.COM_APK_DOWNLOAD_PERCENTAGE, progress[0]);
sendBroadcast(intentResponse);
}
/**
* After completing background task Dismiss the progress dialog
**/
#Override
protected void onPostExecute(String file_url) {
// dismiss the dialog after the file was downloaded
notificationManager.cancel(0);
installApk(Uri.fromFile(new File(downloadLocation)));
}
}
}
any help would be appriciated...
Finally got answer for my own question.
I managed it with Queue class that is in java.util package.
The code i have been used is below:
public class DownloadApkService extends Service {
private NotificationManager notificationManager = null;
String downloadLocation;
String appId = null;
String appLink = null;
String appName = null;
String isApkFromServer = null;
public boolean isDownloading = false;
public static Queue<QueueData> downloadQueue = new LinkedList<>();
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (isDownloading) {
QueueData queueData = new QueueData();
queueData.setAppId(intent.getStringExtra(Constants.COM_APP_ID));
queueData.setAppLink(intent.getStringExtra(Constants.COM_APP_LINK));
queueData.setIsApkFromServer(intent.getStringExtra(Constants.COM_APK_FROM_SERVER));
queueData.setAppName(intent.getStringExtra(Constants.COM_APP_NAME));
downloadQueue.add(queueData);
Intent intentQueueingApk = new Intent();
intentQueueingApk.setAction(Constants.ACTION_QUEUEING_APK);
sendBroadcast(intentQueueingApk);
return START_NOT_STICKY;
} else {
appId = intent.getStringExtra(Constants.COM_APP_ID);
appLink = intent.getStringExtra(Constants.COM_APP_LINK);
appName = intent.getStringExtra(Constants.COM_APP_NAME);
isApkFromServer = intent.getStringExtra(Constants.COM_APK_FROM_SERVER);
}
Thread thread = new Thread(new MyThread());
thread.start();
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
if (notificationManager != null) {
notificationManager.cancel(0);
}
}
class MyThread implements Runnable {
MyThread() {
}
#Override
public void run() {
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(DownloadApkService.this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(appName).setProgress(0, 0, true)
.setContentText(getResources().getText(R.string.downloading_notification))
.setOngoing(true)
.setAutoCancel(true);
notificationManager.notify(0, notificationBuilder.build());
new DownloadFileFromURL().execute(appLink);
}
}
public void installApk(Uri uri) {
Intent install = new Intent(Intent.ACTION_VIEW);
install.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
install.setDataAndType(uri,
"application/vnd.android.package-archive");
DownloadApkService.this.startActivity(install);
}
/**
* Background Async Task to download file
*/
class DownloadFileFromURL extends AsyncTask<String, String, String> {
/**
* Before starting background thread Show Progress Bar Dialog
*/
#Override
protected void onPreExecute() {
super.onPreExecute();
isDownloading = true;
Intent intentResponse = new Intent();
intentResponse.setAction(Constants.ACTION_DOWNLOADING_APK);
intentResponse.putExtra(Constants.COM_APP_ID, appId);
intentResponse.putExtra(Constants.COM_APK_DOWNLOAD_PERCENTAGE, "0");
sendBroadcast(intentResponse);
}
/**
* Downloading file in background thread
*/
#Override
protected String doInBackground(String... f_url) {
int count;
HttpURLConnection connection=null;
try {
String link=f_url[0].replace(" ","%20");
URL url = new URL(link);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Accept-Encoding", "identity");
int lenghtOfFile = connection.getContentLength();
connection.connect();
// this will be useful so that you can show a tipical 0-100%
// progress bar
// download the file
InputStream input = new BufferedInputStream(connection.getInputStream());
downloadLocation = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/";
String fileName = appName + ".apk";
downloadLocation += fileName;
File sourceFile = new File(downloadLocation);
if (sourceFile.exists()) {
sourceFile.delete();
}
// Output stream
FileOutputStream output = new FileOutputStream(downloadLocation);
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
// publishing the progress....
// After this onProgressUpdate will be called
publishProgress("" + (int) ((total * 100) / lenghtOfFile));
// writing data to file
output.write(data, 0, count);
}
// flushing output
output.flush();
// closing streams
output.close();
input.close();
} catch (Exception e) {
return "fail";
}finally {
if(connection != null)
connection.disconnect();
}
return "success";
}
/**
* Updating progress bar
*/
protected void onProgressUpdate(String... progress) {
// setting progress percentage
Intent intentResponse = new Intent();
intentResponse.setAction(Constants.ACTION_DOWNLOADING_APK);
intentResponse.putExtra(Constants.COM_APP_ID, appId);
intentResponse.putExtra(Constants.COM_APK_DOWNLOAD_PERCENTAGE, progress[0]);
sendBroadcast(intentResponse);
Intent intentQueueingApk = new Intent();
intentQueueingApk.setAction(Constants.ACTION_QUEUEING_APK);
sendBroadcast(intentQueueingApk);
}
/**
* After completing background task Dismiss the progress dialog
**/
#Override
protected void onPostExecute(String file_url) {
notificationManager.cancel(0);
if (file_url.equals("success")) {
Intent intentResponse = new Intent();
intentResponse.setAction(Constants.ACTION_DOWNLOADING_APK_COMPLETE);
intentResponse.putExtra(Constants.COM_APP_ID, appId);
sendBroadcast(intentResponse);
isDownloading = false;
if (isApkFromServer!=null && isApkFromServer.equals("0")) {
Intent intent = new Intent(DownloadApkService.this, UploadApkService.class);
intent.putExtra(Constants.COM_APP_ID, mAppDetails.getId());
intent.putExtra(Constants.COM_APK_FILE_PATH, downloadLocation);
startService(intent);
}
installApk(Uri.fromFile(new File(downloadLocation)));
} else if (file_url.equals("fail")) {
isDownloading = false;
Intent intentResponse = new Intent();
intentResponse.setAction(Constants.ACTION_DOWNLOADING_APK_FAILED);
intentResponse.putExtra(Constants.COM_APP_ID, appId);
sendBroadcast(intentResponse);
}
if (/*isDownloading &&*/ !downloadQueue.isEmpty()) {
QueueData queueData = downloadQueue.poll();
appId = queueData.getAppId();
appLink = queueData.getAppLink();
appName = queueData.getAppName();
isApkFromServer = queueData.getIsApkFromServer();
Thread thread = new Thread(new MyThread());
thread.start();
}
}
}
#Override
public void onTaskRemoved(Intent rootIntent) {
if (notificationManager != null)
notificationManager.cancel(0);
}
}
I hope it's going to be helpful for someone.

AlertDialog and service

Hi i am developing one android app where i upload multipal images to the server using Service that means i upload the images to server even my app is closed from background..
Also i displayed Nootification and displayed progress of image uploading in the notification .
The main problem is that i displayed alert dialog when all uploading is completed.But when i close the app then also that dialog is appeared on the screen.
i.e.
if i pause the app or hide the app then that alert dialog will display at home screen
i want to display alert dialog
here is my service
static public class UploadService extends Service {
private String LOG_TAG = "BoundService";
private IBinder mBinder = new MyBinder();
ArrayList<CustomGallery> listOfPhotos;
int i = 0;
long totalSize=0;
NotificationManager manager;
String response_str = null;
long totalprice = 0;
Notification.Builder builder;
SelectedAdapter_Test selectedAdapter;
NotificationCompat.Builder mBuilder;
String strsize, strtype, usermail, total, strmrp, strprice, strlab, strcity, abc, strdel_type, struname, imageName;
ArrayList<CustomGallery> dataT = new ArrayList<CustomGallery>();
#Nullable
#Override
public IBinder onBind(Intent intent) {
Log.v(LOG_TAG, "in onBind");
return mBinder;
}
#Override
public void onRebind(Intent intent) {
Log.v(LOG_TAG, "in onRebind");
super.onRebind(intent);
}
#Override
public boolean onUnbind(Intent intent) {
Log.v(LOG_TAG, "in onUnbind");
return true;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
selectedAdapter = new SelectedAdapter_Test(getApplicationContext(), dataT);
Toast.makeText(UploadService.this, "Service Started ", Toast.LENGTH_SHORT).show();
manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
listOfPhotos = (ArrayList<CustomGallery>) intent.getSerializableExtra("listof");
strsize = intent.getStringExtra("strsize");
strtype = intent.getStringExtra("strtype");
usermail = intent.getStringExtra("user_mail");
strmrp = intent.getStringExtra("strmrp");
strprice = intent.getStringExtra("strprice");
strlab = intent.getStringExtra("strlab");
strcity = intent.getStringExtra("strcity");
struname = intent.getStringExtra("strusername");
strdel_type = intent.getStringExtra("strdel_type");
abc = intent.getStringExtra("foldername");
manager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(this);
mBuilder.setContentTitle("Picture Upload")
.setContentText("Upload in progress")
.setSmallIcon(R.drawable.ic_launcher);
Intent resultIntent = new Intent(this, SelectPhotos.class);
PendingIntent resultPendingIntent = PendingIntent.getActivity(this, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
resultIntent.setAction("android.intent.action.MAIN");
resultIntent.addCategory("android.intent.category.LAUNCHER");
new UploadFileToServer().execute();
return Service.START_NOT_STICKY;
}
public class MyBinder extends Binder {
UploadService getService() {
return UploadService.this;
}
}
private class UploadFileToServer extends AsyncTask<String, Integer, String> {
#Override
protected void onPreExecute() {
// setting progress bar to zero
super.onPreExecute();
pb.setProgress(0);
}
#Override
protected void onProgressUpdate(Integer... progress) {
Log.v("Abhijit122", "" + String.valueOf(progress[0]) + "%");
pb.setProgress(progress[0]);
tp.setText(String.valueOf(progress[0]) + "%");
Log.e("ef", "df" + incr);
ti.setText((incr+1)+"/"+listOfPhotos.size());
}
#Override
protected String doInBackground(String... params) {
return uploadFile();
}
#SuppressWarnings("deprecation")
private String uploadFile() {
for (incr = 0; incr < listOfPhotos.size(); incr++) {
mBuilder.setProgress(listOfPhotos.size(), incr, false);
manager.notify(1, mBuilder.build());
try {
File f = new File(listOfPhotos.get(i).sdcardPath.toString());
int j = i + 1;
j++;
imageName = f.getName();
totalprice = totalprice + Long.parseLong(strprice);
total = String.valueOf(totalprice);
Log.e("Totalprice", " " + total);
String responseString = null;
final HttpClient httpclient = new DefaultHttpClient();
final HttpPost httppost = new HttpPost(URL); //TODO - to hit URL);
AndroidMultiPartEntity entity = new AndroidMultiPartEntity(
new AndroidMultiPartEntity.ProgressListener() {
#Override
public void transferred(long num) {
publishProgress((int) ((num / (float) totalSize) * 100));
}
});
File sourceFile = new File(listOfPhotos.get(i).sdcardPath);
// Adding file data to http body
entity.addPart("image", new FileBody(sourceFile));
entity.addPart("foldername", new StringBody(abc));
entity.addPart("size",
new StringBody(strsize));
entity.addPart("type",
new StringBody(strtype));
entity.addPart("username",
new StringBody(usermail));
entity.addPart("total",
new StringBody(total));
Log.e("Totalprice", "adf " + total);
entity.addPart("mrp",
new StringBody(strmrp));
entity.addPart("price",
new StringBody(strprice));
entity.addPart("lab",
new StringBody(strlab));
entity.addPart("city",
new StringBody(strcity));
entity.addPart("imagename",
new StringBody(imageName));
entity.addPart("deltype",
new StringBody(strdel_type));
entity.addPart("initflag",
new StringBody(""+initflag++));
entity.addPart("lab_username",
new StringBody(struname));
totalSize = entity.getContentLength();
httppost.setEntity(entity);
HttpResponse response = httpclient.execute(httppost);
HttpEntity r_entity = response.getEntity();
response_str = EntityUtils.toString(r_entity);
Log.d("Dhruva", "" + response_str);
if (r_entity != null) {
Log.v("Abhijit", "" + response_str);
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return response_str;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
mBuilder.setContentText("Upload complete")
// Removes the progress bar
.setProgress(0, 0, false);
manager.notify(1, mBuilder.build());
AlertDialog alertDialog = new AlertDialog.Builder(getApplicationContext())
.setTitle("Success")
.setMessage("Successfully uploaded images...")
.setCancelable(false)
.create();
alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
alertDialog.show();
}
}
}
i want to display alert dialog when all uploading is completed and when i click on ok button i want to start next activity.
This is my way to open next activity after successful uploading of images through service.also i implemented notification then which activity should i open when i click on notification
If there is another way please give me suggestion.

Is it possible to show progress bar when download file via Retrofit 2, Android

I'am currently using Retrofit 2 and i want to download some file from my server.
Can i call back some event to catch percent complete download file to show in notification like this picture
I reference that link, but it is upload, can i do it with same problem?
Link
Is it possible to show progress when using retrofit 2 library?
You can use ResponseBody and set it to OkHttp client and to update progress in UI you can use interface.check this link
As an alternative, you could use an Intent service as described here.
I will show you how I used the above... The only difference is the portion where the file is written to disk.
Define the service:
public class BackgroundNotificationService extends IntentService {
public BackgroundNotificationService() {
super("Service");
}
private NotificationCompat.Builder notificationBuilder;
private NotificationManager notificationManager;
private String mAgentsID;
private String mReportsID;
private String mJobID;
private String mFileName;
#Override
protected void onHandleIntent(Intent intent) {
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel notificationChannel = new NotificationChannel("id", "an", NotificationManager.IMPORTANCE_LOW);
notificationChannel.setDescription("no sound");
notificationChannel.setSound(null, null);
notificationChannel.enableLights(false);
notificationChannel.setLightColor(Color.BLUE);
notificationChannel.enableVibration(false);
notificationManager.createNotificationChannel(notificationChannel);
}
notificationBuilder = new NotificationCompat.Builder(this, "id")
.setSmallIcon(android.R.drawable.stat_sys_download)
.setContentTitle("Download")
.setContentText("Downloading Image")
.setDefaults(0)
.setAutoCancel(true);
notificationManager.notify(0, notificationBuilder.build());
mAgentsID = intent.getStringExtra("AgentsID");
mReportsID = intent.getStringExtra("ReportsID");
mJobID = intent.getStringExtra("JobID");
mFileName = intent.getStringExtra("FileName");
initRetrofit();
}
private void initRetrofit(){
Call<ResponseBody> downloadCall = ApiManager.getJasperReportsService().DownloadAgentReportData(mAgentsID, mReportsID, mJobID, mFileName);
try {
writeResponseBodyToDisk(downloadCall.execute().body(), mFileName);
} catch (IOException e) {
e.printStackTrace();
}
}
private boolean writeResponseBodyToDisk(ResponseBody body, String FileName) {
try {
File SDCardRoot = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
File DownloadedFile = new File(SDCardRoot + File.separator + FileName);
InputStream inputStream = null;
OutputStream outputStream = null;
try {
byte[] fileReader = new byte[4096];
long fileSize = body.contentLength();
long fileSizeDownloaded = 0;
long total = 0;
boolean downloadComplete = false;
inputStream = body.byteStream();
outputStream = new FileOutputStream(DownloadedFile);
while (true) {
int read = inputStream.read(fileReader);
if (read == -1) {
downloadComplete = true;
break;
}
total += read;
int progress = (int) ((double) (total * 100) / (double) fileSize);
updateNotification(progress);
outputStream.write(fileReader, 0, read);
fileSizeDownloaded += read;
Log.d("DOWNLOAD FILE", "file download: " + fileSizeDownloaded + " of " + fileSize);
}
onDownloadComplete(downloadComplete);
outputStream.flush();
return true;
} catch (IOException e) {
return false;
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
} catch (IOException e) {
return false;
}
}
private void updateNotification(int currentProgress) {
notificationBuilder.setProgress(100, currentProgress, false);
notificationBuilder.setContentText("Downloaded: " + currentProgress + "%");
notificationManager.notify(0, notificationBuilder.build());
}
private void sendProgressUpdate(boolean downloadComplete) {
Intent intent = new Intent("progress_update");
intent.putExtra("downloadComplete", downloadComplete);
LocalBroadcastManager.getInstance(BackgroundNotificationService.this).sendBroadcast(intent);
}
private void onDownloadComplete(boolean downloadComplete) {
sendProgressUpdate(downloadComplete);
notificationManager.cancel(0);
notificationBuilder.setProgress(0, 0, false);
notificationBuilder.setContentText("Download Complete");
notificationManager.notify(0, notificationBuilder.build());
}
#Override
public void onTaskRemoved(Intent rootIntent) {
notificationManager.cancel(0);
}
}
And then use the intent service:
private void registerReceiver() {
LocalBroadcastManager bManager = LocalBroadcastManager.getInstance(itemView.getContext());
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("progress_update");
bManager.registerReceiver(mBroadcastReceiver, intentFilter);
}
private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("progress_update")) {
boolean downloadComplete = intent.getBooleanExtra("downloadComplete", false);
//Log.d("API123", download.getProgress() + " current progress");
if (downloadComplete) {
Toast.makeText(itemView.getContext(), "File download completed", Toast.LENGTH_SHORT).show();
}
}
}
};
private void startDownload(String jobID, String FileName) {
Intent intent = new Intent(itemView.getContext(), BackgroundNotificationService.class);
// TODO customze to suit your own needs.
intent.putExtra("AgentsID", mAgentsID);
intent.putExtra("ReportsID", mReportsID);
intent.putExtra("JobID", jobID);
intent.putExtra("FileName", FileName);
itemView.getContext().startService(intent);
}
so you use registerReceiver() on start of your activity and then if you have a button to initiate the download, you in the onClick method run startDownload(). As an extra note, you can customize the intent variables(if you need any), to your needs.

Categories

Resources