Transmit variables from service at onDestroy() to already opened Main-Activity - android

I have a Main-Activity which displays several spinners.
With a Toggle-Button in the Main-Activity I start a service which collects GPS-Data in background that measures the distance and sets some other variables.
When I stop the service with another click on the Toggle-Button in the Main-Activity, I stop the service, so the onDestroy() command is executed in the Service.
Within onDestroy in the Service, I want to submit the variables from the service to the already opened Main-Activity.
I tried that so far without success in the service:
Intent intent = new Intent(this, Main.class);
Bundle b = new Bundle();
Test = 2222;
b.putInt("Test", Test);
intent.putExtras(b);
I do not use the "startActivity(intent);", cause the activity that should the data send to is already open...the Main-Activity.
And on the side of the Main-Activity:
Bundle b = getIntent().getExtras();
if (b != null){
Test = b.getInt("Test");
}
else{
//..oops!
Toast.makeText(Main.this, "Oops...Nothing from service! :(", Toast.LENGTH_SHORT).show();
}
I never get data from the service.
I am trying this cause I need to start the service from the Main-Activity, from the Main activity the user stops the service and gets the values from it, then the Main-Activity should transmit the values from the service AND from the selected spinner values from itself to another activity.
I am trying that now for days and I also find some hints here, but nothing worked for me so far.
Someone any ideas?
Do I have to use a Broadcast-Receiver?
Whats the correct way to do this?

Before destroying the service store the data in shared preference and access it in the main activity

I don't know if this is the best way, but just have the Service you created update a static pojo. If the activity is already open then you could just set a timer to poll a the static pojo from the Activity to see if something has changed through an AsyncTask. When something has been updated in the pojo the AsyncTask can tell the Activity to update the UI accordingly. Then you don't have to play around with silly bundles. Also if your worried about your data getting lost you could always use SQLite. Hope this helps.

You need a broadcast receiver in main activity to get the data.

Related

ObservableObject updateValue doesn't reach the right instance after startActivity

I have a basic Activity which mainly allows the user to change settings and save them. I also have a BroadcastReceiver which is launched on SMS_RECEIVED.
The main point of the app is to vibrate whenever a certain message is received until the user taps a button to make it stop. The activity is only there to allow the user to change settings and press the "Stop" button.
In my onReceive method (BroadcastReceiver), I get the content of the last message received and make the phone vibrate if the message is equal to a certain string. All of that is working perfectly, the problem is when I want to make it stop. Right now, I'm trying to make a "Stop" button appear in the Activity when the phone starts vibrating.
I understand that UI elements should remain in the Activity and so what I'm trying to do is communicate between the Activity and my BroadcastReceiver. I've found here how to do that with an Observer. The problem though is that I want the app to function at any time, even at boot time. It's very easy with a BroadcastReceiver but since it requires the Activity to be shown to allow the user to stop the vibration, I have to start the activity if it isn't started already.
So what I do is this:
Intent i = new Intent(context, MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.putExtra("SMSReceived", true);
context.startActivity(i);
ObservableObject.getInstance().updateValue(true);
The problem is, when there is no instance launched, it creates a new one and sends the extra boolean correctly but the updateValue method doesn't seem to get called at all (due to the previous instance I suppose?) and inversely, when there is an instance launched (in the background) the extra boolean doesn't get passed and the updateValue method gets called correctly.
I suppose I could just launch the Activity on boot and immediately put it in the background but it could cause problems if the user closes the application, at which point it would simply stop working until the user started it again since the Observer would have no instance to send data to.
Do you guys have any idea of what I could do to solve my problem?
If it's not clear I can try to explain further.

Detect if user starts an application, android

Thanks in advance for the help.
I have an app that can be started by either the user physically starting the app (like you would any normal app) or by a repeating service. Depending on what starts the app (the user or the service) I want to preform different initialization actions. How might I be able to detect if an user starts the app without doing anything custom (I imagine that there has to be some kind of built in setting in android for me to determine this)?
If service, that starts your Activity, is yours service, you can put some custom information (using Intent#putExtra for example) in Intent you use to start Activity from Service.
In Activity you can use Activity#getIntent(), that returns the intent that started this activity.
If you started Activity from Service, that Intent will be the one you passed in Service#startActivity, and will have your custom information. Otherwise, that was not your Service, that started your Activity.
That could look somehow like that, for example:
//in Activity
public static final String EXTRA_STARTED_FROM_MY_SERVICE = "com.example.extra_started_from_sevice";
private boolean wasActivityStartedFromService() {
Intent startingIntent = getIntent();
//assuming you will use Intent#putExtra in your service when starting activity
return startingIntent.getBooleanExtra(EXTRA_STARTED_FROM_MY_SERVICE, false);
}
//...
//in Service
//...
Intent startingIntent = new Intent(this, MainActivity.class);
startingIntent.putExtra(MainActivity.EXTRA_STARTED_FROM_MY_SERVICE, true);
startActivity(startingIntent);

How do I start an intent without the flag FLAG_ACTIVITY_NEW_TASK in an Android service?

I am trying to connect to different activities from a custom soft keyboard. I need the activity underneath the keyboard to allow data to be sent without the activity creating a new instance of itself. For example: if the keyboard is over the messaging application, I want to send that application data without losing the current conversation that the user is typing into. I currently have the following code to send data to the activity.
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_STREAM, screenshotUri);
//sendIntent.putExtra("thread_id", (long) 1);
sendIntent.setType("image/*");
startActivity(sendIntent);
I am getting the following obvious error when I try to run it...
E/AndroidRuntime(6129): android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
How can I keep the current activity underneath the keyboard from resetting itself when an intent is sent from the keyboard service? Or more simply, how can I send an intent from a service without setting the FLAG_ACTIVITY_NEW_TASK flag?
You can't really do this like that. A Service can't pass data to an Activity without "starting it". You don't want to do that. You want to pass data to an "already started" Activity. There's 2 ways to do this:
Use a bound Service. Have the Activity bind to the Service. The Activity can then call methods on theService (using AIDL) and receive returned data.
Use a BroadcastReceiver. Have the Activity create and register a BroadcastReceiver to listen for the returned data. In your Service, send a broadcast Intent when you want to transmit data to the Activity.
You can do this by several ways but you must set flag in order to complete task.
If you want to create a new instance and close the current instance you need to set Intent.FLAG_ACTIVITY_CLEAR_TOP.
If you want to reuse the same instance of the activity in this case you need to set both Intent.FLAG_ACTIVITY_CLEAR_TOP and Intent.FLAG_ACTIVITY_SINGLE_TOPafter that it will not create another instance of the activity but call onNewIntent() of activity to run the new Intent.

Android intent service onClick, or start new activity and then Asynctask

Many times in android apps, users click a button/view and start a new activity, where the new activity pops up in front of what the user was previously looking at, and loads data.
Would there be any difference from a user perspective if the data started loading (from network or disk or both) when the user clicked the button before the next activity started. And then that data was returned to the new activity in a broadcast receiver.
This is compared to starting the process in the oncreate of the activity. Assuming these network and i/o processes only take milliseconds either way, would it make a difference to the user if the methods were started in onCreate of the new activity, or started in the old activity onClick.
First way, starting I/O and changing views after I/O finishes
//first activity
public void onClick(View v){
startActivity(new Intent(this, NewActivity.class);
}
//NewActivity.class
onCreate(Bundle mBundle){
super.onCreate(mBundle);
setContentView(R.layout.mView);
mObject = networkCall(); //after network call, the view objects in this layout will reflect data from the network call
}
second way, starting the I/O in the first activity
//first activity
public void onClick(View v){
IntentService networkCall = new IntentService();
//start network call
startActivity(new Intent(this, NewActivity.class);
}
//second activity on create just sets the view and also broadcast receiver
My GUESS is that in the split second that it takes for the activity to pop up, the data from the intent service could become available. But at the same time, passing data via intent could take just as long making the benefits marginal
Insight appreciated
In my experience the onCreate() of your new activity is called almost instantly from when you call startActivity(). The new activity doesn't show up right way because it has to take time to render your layout.
You could play around with timings yourself by using the Log.d() function. Something like Log.d(TAG, "This happend at: " + System.currentTimeMillis()); at different points in your code to see when things happen. Watch the LogCat while your apps runs and you can decide for your self which way is better.

When passing data between Activities with Intent Extra I keep getting the same value

In my game I am trying to pass the score from the PlayGame activity to the Scoreboard activity using an Intent Extra.
On finishing the game, I go to the scoreboard in this way:
Intent intentScoreboard = new Intent(getApplicationContext(), Scoreboard.class);
intentScoreboard.putExtra("com.example.game.SCORE", score_counter);
startActivity(intentScoreboard);
and then in the Scoreboard class I retrieve it in the onResume() method like this:
Bundle b = getIntent().getExtras();
int score = b.getInt("com.example.game.SCORE");
This works fine the first time, but if I then play another game and on finishing return to the scoreboard, I still get the score from the first game.
What am I missing?
you are missing calling setIntent()
try this:
let your score activity do a finish() if you get back to start a new game
then it should be working
getIntent delivers the intent which started the activity. If the activity is resumed you get not the most recently received intent. See here for the solution: https://stackoverflow.com/a/6838082/1127492
Bundle is not much needed to receive getExtra() values.
In my code, i have used to receive like this,
int score = getIntent().getIntExtra("com.example.game.SCORE",defaultValue);
It should works for your problem. And also it won't gives you the already received values.
Hope it sounds good for you dude.

Categories

Resources