Send data to BroadcastReceiver that is broadcasted in DownloadManager? [duplicate] - android

I am trying to pass an object to a BroadcastReceiver which will do something when a download is finished. How do I access the Intent object in the BroadcastReceiver's onReceive method from my activity? Right now I have this in my activity:
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
long id = manager.enqueue(request);
and I have this in my BroadcastReceiver that does stuff when the download is complete:
DownloadManager mgr = (DownloadManager)context.getSystemService(Context.DOWNLOAD_SERVICE);
It all works fine, my BroadcastReceiver does what I want when the download completes. But now I want to pass an object from my activity to the BroadcastReceiver. Usually, I would just create an Intent and add the object to the Intent. But, I haven't created an Intent in my code because the BroadcastReceiver responds to the download using the Context.DOWNLOAD_SERVICE.
In my BroadcastReceiver, I want to get data from the Intent object in the onReceive() method here:
#Override
public void onReceive(Context context, Intent intent)
{
intent.getParcelableExtra("object");
}
How do I pass data into this Intent object from my activity? How do I access it? I tried using getIntent().putExtra("object", object) but it seems to be a different Intent than the one used in the BroadcastReceiver's onReceive method because I get a nullPointerException
Edit: here is my relevant code in AndroidManifest.xml
<receiver
android:name="com.android.devon.appfrenzy.DownloadReceiver"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
</intent-filter>
</receiver>

But now I want to pass an object from my activity to the BroadcastReceiver.
That's not possible. The BroadcastReceiver does not exist, except when receiving the broadcast. Your entire process is perhaps gone by the time the download is complete.
You are welcome to store something in a persistent location (SharedPreferences, database, file) and read that in from onReceive(). That's the only way to pass data to an object that does not exist in a process that may not yet exist.

Before download is executed, save the value in SharedPreference
editor.putInt(MainActivity.CERIS_LAST_DW_ID_KATALOG, m_intIdKatalog);
editor.commit();
Then in onReceive get the value from Shared Preference
#Override
public void onReceive(Context arg0, Intent arg1) {
// TODO Auto-generated method stub
SharedPreferences mCeris;
mCeris = arg0.getSharedPreferences(MainActivity.CERIS_PREFERENCES,
Context.MODE_PRIVATE);
int m_intIdKatalog = mCeris.getInt(MainActivity.CERIS_LAST_DW_ID_KATALOG, 0);
}

I was struggling with this because using local storage doesn't work if you're trying to keep track of multiple queued downloads. Luckily the brainiancs at Google pass the Download ID through as an extra, so you can use:
long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0)
Then use
public class DownloadReceiver extends BroadcastReceiver
{
#Override
public void onReceive(final Context context, final Intent intent)
{
long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0)
DownloadManager manager = (DownloadManager) context.getSystemService(DOWNLOAD_SERVICE);
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(downloadId);
Cursor cursor = manager.query(query);
if (cursor.moveToFirst()) {
int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
int reason = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_REASON));
}
cursor.close();
}
}

while calling send broadcast send data as
Intent i = new Intent();
i.putExtra("string_example", "here is a broadcasted string");
i.putExtra("int_example", 100);
sendBroadcast(i);
and in side onReceive() get data from Intent as
#Override
public void onReceive(Context context, Intent intent) {
Log.d(getString(R.string.app_name), "broadcast string: " + intent.getStringExtra("string_example"));
Log.d(getString(R.string.app_name), "extra!: " + intent.getIntExtra("int_example",0));
}
Modify as ur need...

Related

Running tasks from broadcast receiver while app is closed [Android]

I have an app that downloads data and put it into an SQLite Database when a notification is issued. This works fine while the app is in use but I need it to work when the app is closed too.
I have set up a BroadcastReceiver within that is called when the app is closed but I'm not sure how to get it to continue with adding to the database.
Here is the code I am using:
AndroidManifest.xml
<manifest....
<application...
<receiver android:name=".broadcast.PacksReceiver" >
<intent-filter>
<action android:name="ADD_PACK" >
</action>
</intent-filter>
</receiver>
PacksReceiver
public class PacksReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("PacksReceiver", "onReceive");
String message = intent.getStringExtra("message");
PacksActivity pa = new PacksActivity();
pa.downloadPack(null, message);
}
}
PacksActivity
public void downloadPack(View v, String thisPackID){
Log.d("download", "pack");
//THIS LOG IS CALLED EVERYTIME
vRef = v;
if(vRef != null){
runOnUiThread(new Runnable() {
#Override
public void run() {
onScreenProgressBar = (ProgressBar) vRef.findViewById(R.id.onScreenProgress);
onScreenProgressCircle = (ProgressBar) vRef.findViewById(R.id.onScreenProgressCircle);
dlPercent = (TextView) vRef.findViewById(R.id.dlPercent);
onScreenProgressCircle.setVisibility(View.VISIBLE);
onScreenProgressBar.setVisibility(View.VISIBLE);
onScreenProgressCircle.setProgress(0);
}
});
}
if(thisPackID == null){
thisPackID = pack_id;
}
String url = MyApp.getAppContext().getString(R.string.serverURL) +
MyApp.getAppContext().getString(R.string.getAppendixA) + "/" + thisPackID;
Intent appA_Intent = new Intent(Intent.ACTION_SYNC, null, this, DownloadService.class);
appA_Intent.putExtra("url", url);
appA_Intent.putExtra("onCreate", "false");
appA_Intent.putExtra("receiver", downloadPackReceiver);
appA_Intent.putExtra("downloadType", "GET_APPENDIX_A");
appA_Intent.putExtra("requestId", 101);
MyApp.getAppContext().startService(appA_Intent);
}
start the Service from
onReceive()
method because you can get mutiple broadcast one after another.
Write the code to add data in your database in your PackReciever inside OnRecieve() Method because that is where you recieve push notifications.
Don't call activity inside the receiver. Instead, use IntentService to download all packs. IntentService automatically finishes once it completes its work.
Override its onHandleIntent() method and download packs and save to database there.

Broadcasting custom intent from one service to another

I have two services. I need to broadcast custom intent with data from one service. and in second service I need to receive it. I have tried following:
In first service:
public String ACTION_CHANGE_TIME_FORMAT = "com.example.agile.mywatchface.changetimeformat";
Intent timeFormatIntent = new Intent();
timeFormatIntent.putExtra("format", 12);
timeFormatIntent.setAction(ACTION_CHANGE_TIME_FORMAT);
LocalBroadcastManager.getInstance(this).sendBroadcast(timeFormatIntent);
In Second Service:
public String ACTION_CHANGE_TIME_FORMAT = "com.example.agile.mywatchface.changetimeformat";
public class TimeFormatReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
Log.d(MyPreferences.LOGCAT_TAG, "Time format Broadcast received: ");
format = intent.getExtras().getInt("format", 0);
updateTime();
}
}
and I have registered and unregistered receivers properly in second service:
IntentFilter timeFormatIntentFilter = new IntentFilter();
timeFormatIntentFilter.addAction(ACTION_CHANGE_TIME_FORMAT);
MyWatchfaceService.this.registerReceiver(timeFormatReceiver, timeFormatIntentFilter);
Is there anything wrong here? I can't get data(format).
Edit: onRecieve() is not calling.
In Second Service:
Change format = intent.getExtras().getInt("format", 0); to format = intent.getIntExtra("format", 0);
The intent.getExtras() will return the Bundle which put by Intent.putExtras(Bundle bundle), but you didn't do it.
1_ Check that your onReceive() method is called. If not, your Receiver still does not registered.
2_ if (1) is OK, try int format = intent.getIntExtra("format", 0);
P/S: I dont know where do you use the "format" variable, consider use it as local variable and pass it like a parameter.
int format = intent.getIntExtra("format", 0);
updateTime(format)

onReceive not being called when BroadcastReceiver is registered using LocalBroadcastManager

I've created a BroadcastReceiver to receive ACTION_DOWNLOAD_COMPLETE when my app starts downloading something using DownloadManager. As I want to capture ACTION_DOWNLOAD_COMPLETE only when downloading is started from my app, I've used LocalBroadcastManager.
But onReceiver is not being called at all. DownloadManager app shows that download is complete but onReceive is not triggered. When I use registerReceiver it works as expected. But this would let app being notified even if downloading is started by some other app. So LocalBroadcastManager is desired.
MainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
downloadReceiver = new DownloadReceiver();
LocalBroadcastManager.getInstance(this).registerReceiver(downloadReceiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
if(FileHelper.isStorageAvailable()) {
DownloadManager.Request request = new DownloadManager.Request(Uri.parse("http://example.com/image.jpg"));
downloadManager.enqueue(request);
}
}
#Override
protected void onPause() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(downloadReceiver);
super.onPause();
}
DownloadReciever
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);
downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(downloadId);
Cursor c = downloadManager.query(query);
if (c.moveToFirst()) {
int columnIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS);
if (DownloadManager.STATUS_SUCCESSFUL == c.getInt(columnIndex)) {
String title = c.getString(c.getColumnIndex(DownloadManager.COLUMN_TITLE));
Toast.makeText(context, title, Toast.LENGTH_SHORT).show();
}
}
}
}
It simply don't call onRecieve as it should. Point out if I'm doing something wrong here. Been stuck here for quite time now. I can't use registerReceiver as I need to track download complete action only if my app starts downloading.
As I want to capture ACTION_DOWNLOAD_COMPLETE only when downloading is started from my app, I've used LocalBroadcastManager.
That is not going to work. DownloadManager does the download in a separate process, and it will use a system broadcast. The only broadcasts that you can receive via LocalBraodcastManager are the ones that you broadcast via LocalBroadcastManager.

Receive download manager download complete intent and compare id - android

I am using download manager in my activity to download a file. I want to receive the ACTION_DOWNLOAD_COMPLETE intent using a broadcast receiver and match the id of the download request with the id in the intent set by download manager to check if it is the same download.
There are two options:
1) receive the intent in the activity by making a intent filter and registering a broadcast receiver. Problem here is that the broadcast receiver exists within the activity and gets destroyed with it. So if the download doesn't get completed before the activity is destroyed there is no way to receive the intent.
this.downloadId = manager.enqueue(request);
downloadID is compared with the EXTRA_DOWNLOAD_ID of the intent in onReceive method to check if it is the same download. downloadId variable is accessible inside the onReceive method.
2) receive the broadcast via manifest. Problem here is that the onReceive method does not have access to the downloadId variable set inside the activity. So I cannot check if the download is the one I need.
Am I doing it wrong? Basically I want to know if the download was completed successfully or not even if the activity/service where the download started is destroyed.
I hope my question is clear enough.
surely your first option is not good because you must do some work as soon as your download is completed so i suggest you use the second approach and store the downloadid in sharedpreferance or in a file and in onRecieve method check that by stored value. you can also use database but if you want to store just one variable (downloadid) in it, it is not a good idea because you must create table and ...
so let's see some code:
in your activity after saving your downloadid to a variable put it in a SharedPreferences file like:
SharedPreferences settings = getSharedPreferences("DownloadIDS", 0);
SharedPreferences.Editor editor = settings.edit();
editor.putLong("savedDownloadIds", your download id);
editor.commit();
and in onReceive:
#Override
public void onReceive(Context context, Intent intent) {
SharedPreferences downloadids = context.getSharedPreferences("DownloadIDS", 0);
long savedDownloadIds = downloadids.getLong("savedDownloadIds", 0);
Bundle extras = intent.getExtras();
DownloadManager.Query q = new DownloadManager.Query();
Long downloaded_id = extras.getLong(DownloadManager.EXTRA_DOWNLOAD_ID);
if(savedDownloadIds == downloaded_id ){ // so it is my file that has been completed
q.setFilterById(downloaded_id);
DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
Cursor c = manager.query(q);
if (c.moveToFirst()) {
int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
if (status == DownloadManager.STATUS_SUCCESSFUL) {
// do any thing here
}
}
c.close();
}
}
//Fetching the download id received with the broadcast
long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);

Android DownloadManager

I am using Android DownloadManager to download some file say of XMB if DownloadManager completes download it will send broadcast of action android.intent.action.DOWNLOAD_COMPLETE in normal scenario.
My question is what if the internet connection gets lost in between. Will it send any broadcast? Same case in between if server stops serving what DownloadManager does. Maybe its silly question, I have very small file so I am unable to test this scenario.
Could some one tell me what DownloadManager does in these kind of scenarios?
The broadcast will be sent. You need to check the status of DownloadManager to determine if it was successful. For example:
private DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);
Query query = new Query();
query.setFilterById(enqueue);
Cursor c = dm.query(query);
if (c.moveToFirst()) {
int columnIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS);
if (DownloadManager.STATUS_SUCCESSFUL == c.getInt(columnIndex)) {
// handle data
} else if (DownloadManager.STATUS_FAILED == c.getInt(columnIndex)) {
// handle error
}
}
}
}
};
For a full example, see: this link. For ways to determine the reason of the failure, see this link.
Courtesy : Android DownloadManager Example
I register my receiver for DownloadManager.ACTION_DOWNLOAD_COMPLETE broadcast only. This is invoked only when the download is successfully completed
Follow this three steps
Create a BroadcastReceiver as shown in snippet below.Inside the receiver we just check if the received broadcast is for our download by matching the received download id with our enqueued download.
private BroadcastReceiver onDownloadComplete = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//Fetching the download id received with the broadcast
long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
//Checking if the received broadcast is for our enqueued download by matching download id
if (downloadID == id) {
Toast.makeText(MainActivity.this, "Download Completed", Toast.LENGTH_SHORT).show();
}
}
};
Once the BroadcastReceiver is created you can register for ACTION_DOWNLOAD_COMPLETE in the onCreate method of your activity.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
registerReceiver(onDownloadComplete,new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}
It is also important that you unregister the BroadcastReceiver in onDestroy. This ensures you only listen for this broadcast as long as the activity is active
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(onDownloadComplete);
}
Complete example here

Categories

Resources