I have an android app that gets FCM Data messages (contains Image URL).
When Data Message is received in onMessageReceived()
I create a FirebaseJobDispatcher
and a Job, then schedule the Job for downloading and saving image in local storage dispatcher.mustSchedule(myJob)
.
The download and save image Job extends JobService
. When a Job is started I create a Thread to in which I download and save the Image, then I send a BroadcastReceiver
to the Activity so that it displays the new image from Local Storage in ImageView using Picasso (code below):
private String imageName = "image.jpg";
@Override
public boolean onStartJob(final JobParameters jobParameters) {
Log.d(TAG, "Update local storage content with new Image!");
Target target = new Target() {
@Override
public void onBitmapLoaded(final Bitmap bitmap, Picasso.LoadedFrom from) {
// Delegating work to a new Thread since it can be long task (downloading Image and storing it to local file system)
Thread storeImageThread = new Thread(new Runnable() {
@Override
public void run() {
// File file = new File(Environment.getExternalStorageDirectory().getPath() + "/" + imageName);
File file = new File(getApplicationContext().getFilesDir(), imageName);
try {
file.createNewFile();
FileOutputStream ostream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 75, ostream);
ostream.flush();
ostream.close();
} catch (IOException e) {
e.getLocalizedMessage();
}finally {
Intent intent = new Intent("com.example.SendBroadcast");
//intent.putExtra("imageURL", remoteMessage.getData().get("image"));
intent.setAction("com.example.SendBroadcast");
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
// sendBroadcast(intent);
sendOrderedBroadcast(intent,null);
//Tell the framework that the job has completed and does not need to be reschedule
jobFinished(jobParameters, true);
}
}
});
storeImageThread.start();
}
@Override
public void onBitmapFailed(Drawable errorDrawable) {
}
@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
};
Picasso.with(getApplicationContext())
.load(jobParameters.getExtras().getString("image"))
.into(target);
return true;
}
I am facing some problems with this architecture;
- The Job Service starts many times very late although I use setTrigger(Trigger.executionWindow(0, 0))
. So should I use a Firebase Job Dispatcher with Job Service for downloading and saving image in local storage? Is there any other alternative?
Is there more performance and efficient way to update the activity after finishing download and saving image?
I think Picasso uses separate Thread to download Image, so is my Thread use here correct?
Many times I am getting ARN dialog and app crashes. So is there a more performance architecture proposal for my purpose?
Thanks in advance for any help from experts
Because your application is running state when
onMessageReceived
is executed for FCM message. no need to use Firebase Job DispatcherYes, use WorkManager for downloading image if app is not visible to user. save image in cache or sdcard and show it when app opened by user.
WorkManager providing options for checking task is finished or not before starting same task again.
OR
If app is already running then use normal service like
IntentService
orService
.