I currently have an intent service that is managing my geofence transitions and I am hoping to use the geofence ID to trigger a sequence of events either by starting an activity through another intent or by broadcasting the relevant string to my main activity so that I can do the process there. currently my code inside my intentservice contains this
String fenceID = fences.get(0).getRequestId();
Log.i( fenceID, "fenceID is");
if (fenceID == Home){
Intent broadcastIntent = new Intent();
broadcastIntent.setAction(PlayerActivity.MyWebRequestReceiver.PROCESS_RESPONSE);
broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
broadcastIntent.putExtra(fenceID, fenceID);
broadcastIntent.putExtra(RESPONSE_MESSAGE, "respone");
sendBroadcast(broadcastIntent);
/* Intent mpdIntent = new Intent(this, PlayerActivity.class)
.setData(Uri.parse("http://maxmarshall.ddns.net/segments/TEST_dash.mpd"))
.putExtra(PlayerActivity.CONTENT_ID_EXTRA, "my test")
.putExtra(PlayerActivity.CONTENT_TYPE_EXTRA, 0);
startActivity(mpdIntent);*/
}
You can see the commented out code is my original idea or end goal (whether it is completed through this set up or in another activity
However even though fenceID is Home I am not getting any response to that effect with this setup. Can anyone shed some light on what I am doing wrong here? I can update the question with more code if anyone needs. perhaps I am not registering my broadcast receiver properly if theres something I need to put in the manifest? anyway thanks very much for any and all help!
You cannot start a new Activity from a Service context in the same task. The only way you can start an Activity from there is to use the flag FLAG_ACTIVITY_NEW_TASK. Make sure you really need it before you implement this.
Your code for sending a broadcast message looks fine. Just make sure you register your receiver properly and it's IntentFilter matches.
Also, never do this:
String fenceID = fences.get(0).getRequestId();
Log.i( fenceID, "fenceID is");
if (fenceID == Home){
The fenceId is a String, i.e. it is a an Object. Comparing with == will give you true only if both references point to the same object. Is this really what you want in this case? Use fenceId.equals(Home) if you want to compare characters instead of objects.
My guess is that your code is never executed because of this mistake in the condition.
Related
I am using an alarmmanger with broadcast receiver and when a specified time occurs, i need to update the MainActivity with extra parameter but its behaving randomly.
here is code in the broadcast receiver
public void onReceive(Context context, Intent intent){
//calculate time
//check time
if(isTime){
Log.d("tag", "sleep");
//set value in shared preference
editor = (context.getSharedPreferences("uniqueId", 0)).edit();
editor.putBoolean("sleepmode",false);
editor.apply();
Intent gotoSmileyScreen = new Intent(context, MainActivty.class);
gotoSmileyScreen.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK );
context.startActivity(gotoSmileyScreen);
}
}
In logcat, i am able to see "sleep" , so i know the method is being called at the right time
Here is code in MainActivity
//inside on create
//get value from shared preference and check
if(!isSleepMode){
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}else{
//do nothing
}
The user will most likely be already in that activity but not necessarily.
The activity is being called for some devices and the screen turns off as expected but for some others, the activity is never called from the intent and screen wont turn off.
From the documentation, Intent.FLAG_ACTIVITY_CLEAR_TASK, should clear the activity before calling it again or am i missing something?
Is there a better way to update the activity from the receiver without calling it again?
Edit: My app is a launcher, does it in any way effect calling the intent?
I found a workaround using Intent.FLAG_ACTIVITY_SINGLE_TOP and overriding onNewIntent in the MainActivity. If the activity is already in the top, it calls onNewIntent otherwise creates a new instance of the activity. So the new code is like this
gotoSmileyScreen.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP );
and it works. Hope it helps someone.
Change your intent as below and try
Intent gotoSmileyScreen = new Intent();
gotoSmileyScreen.setClassName("com...<Your broadcast receiver name>", "com.....MainActivty.class");
gotoSmileyScreen.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(gotoSmileyScreen);
For Broadcast receiver try like above.
Another way to update the activity is by using Dynamic Broadcast receiver
To acheive this inside the onReceive Method use sendBroadcast to send the data to activity ad inside the activity
register the broadcast Receiver to receive the data
Register your dynamic broadvast Receiver inside onCreate() and unregister inside onDestroy()
An app I'm working on can receive asynchronous events in the background. The way I've architected the app, when the client receives such events, it sends a Message to a Handler that an Activity owns. The activities handles messages in various ways.
In one scenario, when a particular event arrives while the app is not in the foreground, I need to bring up an Activity and some UI to the user. Like how when a call arrives, the Answer or Decline UI comes to the foreground no matter what other app is currently active.
What's the best way to do this? I'm re-reading the documentation on Activities, Intents, and Tasks, but it's not always clear or easy to digest. I'm also actively looking for example code or tutorials that do similar things, but no luck there so far. Any pointers or references are welcomed.
You mean like
startActivity( new Intent(this, YourClass.class), Intent.FLAG_ACTIVITY_NEW_TASK);
Edit: ah you don't have the background stuff yet
`
private IntentFilter mNoticeFilter = new IntentFilter("com.you.yourapp.NEW_NOTICE");
private BroadcastReceiver mNoticeReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Do something! ie launch your activity
startActivity( new Intent(this, YourClass.class));
}
};`
When you create your activity then you can
registerReceiver(mNoticeReceiver, mNoticeFilter);
and don't forget to unregisterReceiver(mNoticeReceiver);
see here: http://developer.android.com/reference/android/content/BroadcastReceiver.html
Sounds like you need a BroadcastReceiver.
In this code snippet, what Activity class do I use? The one where the code is written? Is this statusbar message going somewhere?
Intent notificationIntent = new Intent(this, MyActivity.class);
Does this method act immediately or it's done later?
NotificationManager.notify();
In this code snippet, what Activity class do I use?
How should we know? We are not mind readers, and you have given us one line out of a much larger example somewhere.
Taking a completely random guess, that is probably the activity that should be opened when the user taps on the notification entry.
Does this method act immediately or it's done later?
The call is asynchronous, but it should be displayed almost immediately.
I'm just getting into Android development, and I have a question about communicating between a receiver class and an activity class. I'm very new to JAVA and Android so I hope I don't sound too stupid. I'm developing an application where I intercept an SMS message and then based on various elements of that SMS I might delete it once it's been saved to the inbox. I have a receiver class that intercepts the txt message, and I am also able to delete messages from my inbox with code in the activity class using a button at the moment. The problem I have is communicating between the receiver class and the activity class where the code to delete a message resides. I tried putting that code directly into the receiver class but as I'm sure most of you already know the BroadcastReceiver class doesn't seem to support what I need to delete messages. I've been searching for an answer to this for a while, but haven't been able to find anything. Honestly I'm not sure I know enough about JAVA and Android to even recognize a solution if I saw it.
If you need to complete a job without an interface look into creating a Service, if you need user interface just start an Activity
You can use the Context parameter of the onReceive method of the receiver to start a new service/activity
You can use Extras to pass params between context. So you can put as extra the message id or entire message and pass it to your service/activity and deal it there.
You could implement the handling messages logic using an IntentService. When your receiver gets the new incomming message, start the IntentService passing an intent with the message data.
Receiver
onReceive(Context context, Intent intent) {
//Setup Intent
Intent i = new Intent(context, MyIntentService.class);
i.setAction(MyIntentService.HANDLE_MESSAGE);
//Pass data to intent
i.putExtra(MyIntentService.MESSAGE_DATA, data);
//Start Intent Service
context.startService(i);
}
MyIntentService
onHandleIntent(Intent i){
String action = i.getAction();
if(action != null && action.equals(MyIntentService.HANDLE_MESSAGE){
//Get data and implement message logic
}
}
Hope it helps.
At the moment I am developing an application which catches the action NEW_OUTGOING_CALL with the help of a BroadcastReceiver. I am aborting the call by calling setResultData(null). After that I am showing the user a dialog which allows him to decide if he wants to use my application to rewrite its number. When the users decision has happened I am placing the new call depending on the decision. Now my broadcast receiver gets called up once again.
What is the correct way of getting to know that I have already processed the number? I got a working solution that uses a timestamp to guess if it could be already processed. Another solution would be to add a "+" at the end of the processed number.
These methods are working fine for my application being the only one catching the NEW_OUTGOING_CALL event. But what should I do when other applications (like Sipdroid or Google Voice) are also sitting there catching the NEW_OUTGOING_CALL broadcast aborting it and restarting it again? I don't see a possibility to get to know if we are still in the same "call flow" and if I already processed the number.
I would love to hear your ideas about this problem!
What API level are you working with? If it's >= 11, check out the new BroadcastReceiver.goAsync function that lets you extend the processing of the broadcast outside of the onReceive function of your receiver. This could bypass the need to loop altogether.
If, like me, you're stuck trying to do this before level 11, it is surprisingly tricky to do this elegantly. You may have done this as well, but I tried to include a "processed" flag as an extra in the ACTION_CALL intent that my code generated, hoping that it would somehow get included in the resulting ACTION_NEW_OUTGOING_CALL broadcast, but that sadly does not work.
The best solution I have been able to find is including a fragment in the URI for the ACTION_CALL intent that you generate. This fragment will be included for the resulting ACTION_NEW_OUTGOING_CALL broadcast, so your broadcast receiver can differentiate between the original call and the one that you generate, but it won't interfere with handlers that aren't looking for it.
Here's the basic code.
In your BroadcastReceiver for the ACTION_NEW_OUTGOING_CALL
public class YourBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// extract the fragment from the URI
String uriFragment = Uri.parse(
intent.getStringExtra("android.phone.extra.ORIGINAL_URI")).getFragment();
// if the fragment is missing or does not have your flag, it is new
if (uriFragment == null || !uriFragment.contains("your_flag")) {
// launch your activity, pass the phone number, etc.
// use getResultData to get the number in order to respect
// earlier broadcast receivers
...
// abort the broadcast
this.setResultData(null);
this.abortBroadcast();
}
// otherwise, your code is there, this call was triggered by you
else {
// unless you have a special need, you'll probably just let the broadcast
// go through here
// note that resultData ignores the fragment, so other receivers should
// be blissfully unaware of it
}
}
}
When the user first dials the number, the fragment will either be missing altogether or your flag won't be present, so you'll abort the broadcast and start your activity. In your activity, if you decide to place the call again, do something like the following:
startActivity(new Intent(Intent.ACTION_CALL,
Uri.parse("tel:" + modified_number + "#your_flag")));
The "your_flag" fragment will then be present in the subsequent NEW_OUTGOING_CALL broadcast and thus allow you to handle this case differently in your broadcast receiver.
The nice thing about this is the the fragment is completely ignored unless you look for it in the ORIGINAL_URI, so other broadcast receivers can continue to function. If you want to be really nice, you may want to look for an existing fragment and add your flag to it (perhaps with a comma separator).
I hope that helps. Good luck!
I don't see a possibility to get to
know if we are still in the same "call
flow" and if I already processed the
number.
Technically, you are not in the same "call flow" as placing a new call is asynchronous. You have to use hints (such as a timestamp) as you seem to be doing already.
If you are confident that other applications will not rewrite the number except to change the prefix or to add a suffix, you may want to add another "proximity check" hint to avoid false positives/negatives, but I'm afraid that's about all you can do.
The onReceive() method in Broadcast receiver receives an Intent as an argument.
Extract the Bundle from the Intent using Intent.getExtras().
This Bundle contains 3 key-value pairs as follows :
android.phone.extra.ALREADY_CALLED = null
android.intent.extra.PHONE_NUMBER = 98xxxxxx98
android.phone.extra.ORIGINAL_URI = tel:98xxxxxx98
98xxxxxx98 is the number dialled by the user.
When the onReceive() is called again, this number changes to 98xxxxxx98* or 0*
By checking for the asterisk(*) at the end of the dialled number, it can be inferred if the onReceive() method is called for the first time or the next subsequent times.
One of the answers would be to track the boolean extra in the intent. It is done in similar way by the Google Phone app. You can check this BroadcastReceiver here (look for alreadyCalled usage)
The other way would be just to pass that "rewritten" number from your broadcast to the next broadcast receiver down the road (can be any app, like Sipdroid, Google Voice, or custom VoIP app) without calling ACTION_CALL intent (this is why you get loop and you broadcast receiver called again) The following code is example of how I am handling call in my custom VoIP app. When I intercept NEW_OUTGOING_CALL in my broadcast receiver, I first check if there is internet connection. If phone is connected to internet I use custom defined intent action of my activity to place call through my VoIP app. If there is no internet connection, I just set original phone number to the broadcast receiver result data. This is used by the next broadcast receiver (probably default phone app, but doesn't have to be) in the flow to place a call.
public class BHTTalkerCallReceiver extends BroadcastReceiver {
private static final String TAG = "BHTTalkerCallReceiver";
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Broadcast successfull ... ");
// Extract phone number reformatted by previous receivers
String phoneNumber = getResultData();
if (phoneNumber == null) {
// No reformatted number, use the original
phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
}
if (isNetworkAvailable(context)) { // Make sure this app handles call only if there is internet connection
// My app will bring up the call, so cancel the broadcast
setResultData(null);
// Start my app to bring up the call
Intent voipCallIntent = new Intent(context, TalkerActivity.class);
voipCallIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
voipCallIntent.putExtra(TalkerActivity.OUT_CALL_NUMBER, phoneNumber);
voipCallIntent.setAction(TalkerActivity.BHT_TALKER_OUT_CALL);
context.startActivity(voipCallIntent);
} else { //otherwise make a regular call...
// Forward phone data to standard phone call
setResultData(phoneNumber);
}
}
private boolean isNetworkAvailable(final Context context) {
final ConnectivityManager connectivityManager = ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE));
return connectivityManager.getActiveNetworkInfo() != null && connectivityManager.getActiveNetworkInfo().isConnected();
}
}