My requirement is when a push notification comes in my device, I need to call an Asynctask. The app can be running in background. I shouldn't click the notification, instead when it comes I need to call Asynctask. Is that possible?
In your GCMIntentService just override onMessage(..) method this method called when push notification is comming in device.
#Override
protected void onMessage(Context context, Intent intent) {
mContext = context;
final String message = intent.getStringExtra("message");
Log.e(TAG, "GCM Received message : "+message);
AsyncTask<Void, Void, Void> DatabaseOperationTask = new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
// do your Database Operation here
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
};
DatabaseOperationTask.execute();
}
Yes it is possible
you have GCMIntentService which have the method
#Override
protected void onMessage(Context context, Intent intent)
{
}
this method receives message and generate notification you can execute your async task in this method if you need any context the service has its own context
Related
I have a Class (BroadcastReceiver) as
public class AlarmReceiverActivity extends BroadcastReceiver
{
public String memtypefrommainactivity="";
Context mContext;
#Override
public void onReceive(Context context, Intent intent)
{
context=mContext;
memtypefrommainactivity = intent.getStringExtra("memtypetobroadcast");
new CheckNewMessages(context).execute(memtypefrommainactivity);
}
And in the same class I have one Asynctask :
protected class CheckNewMessages extends AsyncTask<String,Void,String> {
public CheckNewMessages(Context context)
{
mContext=context;
}
#Override
protected void onPreExecute() {
}
#Override
public String doInBackground(String... params)
{
if(memtypefrommainactivity=="Retired".toString())
{
URL="xyz.com";
}
I didn't get the value of memtypefrommainactivity from both reference memtypefrommainactivity and params[0].
A BroadcastReceiver has an extremely short lifetime. Basically after onReceive() returns, the BroadcastReceiver is dead. As stated in the documentation, you cannot start asynchronous or long-running activities from a BroadcastReceiver and expect to get any callbacks. You need to use a Service instead of AsyncTask. Your BroadcastReceiver should start a Service to do the work, passing it the necessary parameters. Youc an probably do away with the BroadcastReceiver entirely and just have the AlarmManager start the Service directly.
I'm not sure if my current approach is the proper way to use a Service: I would like to listen to a LocalBroadcastManager in the background (no Activity involved) and query some WebServices upon receiving an Intent. Could you please have a look at my code below and tell me if this is "good" or "bad" in regards of a robust code design? Of course I'd like to reduce the device resource utilisation to a minimum.
Originally, I had an IntentService in my mind but I didn't figure out how to start it from a BroadcastReceiver (you can't register a BroadcastReceiver in the manifest if it just listens to LocalBroadcasts).
public class WebRequestService extends Service {
#Override
public void onCreate() {
BroadcastReceiver mLocalMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
new getCurrentValues().execute();
}
};
IntentFilter messageFilter = new IntentFilter(Intent.ACTION_SEND);
LocalBroadcastManager.getInstance(this).registerReceiver(mLocalMessageReceiver, messageFilter);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
#Override
public void onDestroy() {}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
private class getCurrentValues extends AsyncTask<Void, Void, ResultDTO> {
#Override
protected ResultDTO doInBackground(Void... params) {
// do some magic
return resultDTO;
}
protected void onPostExecute(ResultDTO result) {
if (result != null) {
Intent messageIntent = new Intent();
messageIntent.setAction("currentValuesUpdated");
messageIntent.putExtra("result", result);
LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent);
}
}
} }
Thank you very much
I need to make simple thing: from my app I have to make a photo, send it to server (in background) and show notification after sending. It all works, but now I have to wait for end of sending file - activity with camera is closing after that. I don't want to wait, I want to get back to my main activity right after taking picture (but upload would be still going in thread, and send notification when finishes).
The problem: I don't know how to let know to my main activity, that thread has finished uploading of photo.
Maybe passing context or handler to camera activity would help, but I can't do that by putExtra().
Any suggestions?
Some fragments of my code:
in MainActivity.java:
Intent intent = new Intent(this, Camera.class);
startActivityForResult(intent, Constants.REQUESTCODE_CAMERA);
in Camera.java:
#Override
protected void onCreate(Bundle savedInstanceState) {
//(...)
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
startActivityForResult(intent,TAKE_PHOTO);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//(...)
new SendFileToServer().execute();
// finish(); // I would like to finish Camera.java here, and get back to MainActivity, while SendFileToServer uploads file and send some notification later
}
protected class SendFileToServer extends AsyncTask<Void, Void, String>{
#Override
protected String doInBackground(Void... params){
//(...) // here is sending of file to server, it works
}
#Override
protected void onPostExecute(String result) {
//(...) // code below doesn't work, because I didn't pass "context", I don't know how, or it's just impossible
MainActivity mainActivity = (MainActivity) context;
mainActivity.sendFileName(filename);
}
}
What you can do is send a broadcast on the end of the AsyncTask and register a receiver in the Activity where you want to do something (e.g. show notification).
To do that you will need to:
1) pass an Application Context to your AsyncTask (in Activity):
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//(...)
new SendFileToServer(getApplicationContext()).execute(); // pass application context to AsyncTask
finish();
}
2) Send a broadcast from onPostExecute():
protected class SendFileToServer extends AsyncTask<Void, Void, String>{
private Context context;
public SendFileToServer(Context context) {
this.context = context;
}
#Override
protected String doInBackground(Void... params){
//(...) // here is sending of file to server, it works
}
#Override
protected void onPostExecute(String result) {
Intent intent = new Intent("com.example.UPLOAD_FINISHED");
context.sendBroadcast(intent);
}
}
3) Register a BroadcastReceiver in MainActivity (don't forget to unregister receiver in onPause()):
MainActivity.class
private BroadcastReceiver broadcastReceiver;
#Override
protected void onResume() {
super.onResume();
IntentFilter intentFilter = new IntentFilter(
"com.example.UPLOAD_FINISHED");
broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// show notification
}
};
registerReceiver(broadcastReceiver, intentFilter);
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(broadcastReceiver);
}
In my demo project i am using a GCM for receiving the push message. I need to process the push message i am receiving in a synchronised way.. Once i received my push i need to do some task and send the acknowledgement to my server(the ack. is sent by a Async task).My project is working fine in normal scenario's, but if i switch off my Data Connectivity and if i give 10 push message and then i switch on my Phone's Data connectivity , My GCM is getting Hanged as it receives message as a bunch and after that it is not processing my push. Plz help to solve this problem
MyGCMService.java
public class MyGCMService extends GCMBaseIntentService{
.....
public GCMIntentService() {
...
myThreadClass =new MyThreadClass();
}
#Override
protected void onRegistered(Context context, String registrationId) {
....
}
#Override
protected void onUnregistered(Context context, String registrationId) {
....
}
#Override
protected void onMessage(Context context, Intent intent) {
try{
// System.out.println("*********** 4-3- "+String.valueOf(myThreadClass.getState()).equals("NEW"));
if(String.valueOf(myThreadClass.getState()).equals("NEW"))
myThreadClass.start();
}catch(Exception e){
}
synchronized (myThreadClass) {
...
myThreadClass.wait();
}
}
#Override
protected void onDeletedMessages(Context context, int total) {
...
}
#Override
public void onError(Context context, String errorId) {
....
}
#Override
protected boolean onRecoverableError(Context context, String errorId) {
....
}
public void OnDestroy() {
super.onDestroy();
}
}
MyTreadClass.java
public class MyThreadClass extends Thread {
MyThreadClass myThreadClass;
String LOG_TAG = MyThreadClass.class.getSimpleName();
public void run() {
synchronized (this) {
Looper.prepare();
performAction();
notify();
}
}
public MyThreadClass() {
myThreadClass=this;
}
public void performMDMAction() {
//Doing Some task and Sending Ack. through Async task
}
}
Once this thread Hangs my GCMBaseIntentService, the Override OnMessage() function is not called..
Thanks in Advance
You really shouldn't use low level synchronization methods such as wait and notify. They are very tricky to correctly use.
If you want to perform an asynchroneous task in an Android app, perhaps AsyncTask would be suitable to your needs. If not, consider using the java.util.concurrent package.
I've got a class called Download which extends the AsyncTask.
The OnPreExecute method does the following :
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
this.dialog.setTitle("Check updates...");
this.dialog.show();
}
The dialog listed is instantied in the constructor of the class and has the following charateristics:
dialog = new ProgressDialog(activity);
dialog.setCancelable(false);
In the doInBackground method I'll do a lot of network operations and I'll call the progress update method every time I'm able to download an image from a desired url :
protected void onProgressUpdate(String... values)
// TODO Auto-generated method stub
super.onProgressUpdate(values);
//call the onprogress update
publishProgress("1000");
//do a lot of stuff with the network
}
In the onprogressupdate I'll dismiss the first dialog created and I'll show another one:
protected void onProgressUpdate(String... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
if(values[0].equals("1000")){
dialog.dismiss();
progress_brand.show();
progress_brand.setProgress(progress_brand.getProgress()+1);
if(progress_brand.getProgress() == progress_brand.getMax()){
progress_brand.dismiss();
}
}
}
So basically : at the start of the asynctask I'm showing a dialog with a title "check updates" ... then I'll search for those updates in the doinbackground method and if I'll find some, I'll use the publish progress to dismiss the "old dialog" and create a new one with the ProgressDialog.STYLE_HORIZONTAL. This last dialog is updated everytime I'll download something from the net.
So here's the problem. If I'll run the application with eclipse and then during a download I'll pause the application everything works fine. If I re-enter the application in a second time I can see that the download continues perfectly and I can see the second progress bar continuing to update itself as expected.
If however I make a signed apk --> install the application through that apk --> start the app --> put it on pause during a download -->re-enter the app, then the first dialog is showed again and the download can't proceed properly.
I've seen from the logcat that if I'll run the app from eclipse the onpreexecute method is called only once, even if I'll exit and re-enter in the app.
However if I'll install the app through the apk the onpreexecute method is called everytime I'll exit and then re-start the app.
Why is that happening? I've tried to clean the project and other basic operations to see if the problem was the creation of that apk, but with no results.
no, you do not use ProgressDialog in your AnyTask
try this (for example)
public class Updated extends Activity {
/**
* ProgressDialog which is shown
*/
private ProgressDialog progessDialog_g;
private boolean downloadUses = false;
/**
* Instance of the BroadcastReceiver
*/
private BroadcastReceiver receiver_g;
private IntentFilter iFilter;
protected ServiceConnection mServerConn = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder binder) {
}
public void onServiceDisconnected(ComponentName name) {
}
};
private Intent sI;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.progress);
progessDialog_g = new ProgressDialog(this);
// Reads and sets the settings for the ProgressDialog
// Create the IntentFilter for the different broadcast messages
iFilter = new IntentFilter(
ProgressService.PROGRESS_DIALOG_BROADCAST_FINISH);
// Creates the BroadcastReceiver
receiver_g = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (ProgressService.PROGRESS_DIALOG_BROADCAST_FINISH
.equals(intent.getAction())) {
// Finishs the ProgressDialog
progessDialog_g.cancel();
Finish();
}
}
};
}
#Override
protected void onDestroy() {
super.onDestroy();
}
#Override
protected void onResume() {
sI = new Intent(this, ProgressService.class);
this.bindService(sI, mServerConn, Context.BIND_AUTO_CREATE);
this.startService(sI);
// Registers the BroadcastReceiver
registerReceiver(receiver_g, iFilter);
if (downloadUses) {
downloadUses = false;
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
} else {
progessDialog_g.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progessDialog_g.setMessage("you messege");
progessDialog_g.show();
new DownloadJSONTask(this, sI)
.execute(Initialize.server_url+"/changes/update/1");
}
super.onResume();
}
#Override
protected void onPause() {
this.stopService(new Intent(this, ProgressService.class));
this.unbindService(mServerConn);
unregisterReceiver(receiver_g);
super.onPause();
}
private void Finish() {
Intent in = new Intent(this, RegionsActivity.class);
startActivity(in);
downloadUses = true;
}
}
}
and
public class ProgressService extends IntentService {
public static final String PROGRESS_DIALOG_BROADCAST_FINISH = "Dialog.Progress.MyKey.Finish";
public ProgressService() {
super("ExampleProgressService");
}
/**
* Send the finish message.
*/
private void closeProgressActivity() {
Intent intent = new Intent(PROGRESS_DIALOG_BROADCAST_FINISH);
sendBroadcast(intent);
}
#Override
protected void onHandleIntent(Intent intent) {
// extractVariablesFromIntentAndPrepare(intent);
String action = intent.getStringExtra("Action");
if ("0".equals(action)) {
closeProgressActivity();
}
}
}
and in you AnyTask
sI.putExtra("Action", "0");
context.startService(sI);
and in you manifest
<service android:name=".Intent.ProgressService" />