i have an app with service that works completely background, but sometimes i need to change the content in the foreground activity , for now let's say i want to show Toast.
first i am checking if the app is opened as foreground
public boolean isForeground(String myPackage) {
ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> runningTaskInfo = manager.getRunningTasks(1);
ComponentName componentInfo = runningTaskInfo.get(0).topActivity;
return componentInfo.getPackageName().equals(myPackage);
}
then i want to know what is the running activity
String PKG_Name = componentInfo.getPackageName();
this will give me the name , but what i want is to is get the object Activity ,to do something like this:
activity.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(activity, "Hello", Toast.LENGTH_SHORT).show();
}
});
how can i do it? if not possible, is there's a way to is to send a signal or a message to the service to tell the it?
For that you have two options, if you are fine showing just a Toast and not interact with other elements, you can implement a broadcast reciever and make your custom intent with custom action,
Intent int= new Intent(); int.setAction("Your custom string here");
and then post a toast in your braodcast reciever,
OR
you can use a custom handler to interact with all the objects in foreground and activity, here's some study material for it,
https://developer.android.com/training/multiple-threads/communicate-ui
Related
This problem is a little different from most 'display toast' issues. I am not asking to display Toast messages in other activities but to see Toast messages sent by a background service while in another activity besides the main activity. I DO see the Toast messages in the main activity!
I have an application that has a background service. When certain events happen in this background service a Toast message is displayed. The background service receives data from external BT and BLE devices and sends messages out over wifi. The toast messages show certain important events in those processes. The MainActivity and the background service use the application context from getApplicationContext() for the display of this toast message.
However, these messages do not display if I move to another Activity. For example, to configure some parameters. I am not trying to display toast messages from other activities; that I can do. But how can I get the toast messages from the background service to also display while I am in another Activity besides the MainActivity? I think I will need to do something like 'run the activity on the application context' though I have no idea how to do it (or even if it is possible).
Use BroadcastReceiver for this purpose. In each of your Activity you need to declare a BroadcastReceiver like this.
private class ShowToastBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String message = intent.getStringExtra("Message");
Toast.makeText(OtherActivity.this, message, Toast.LENGTH_LONG).show();
}
}
You need to register the BroadcastReceiver each time in your onResume and unregister it back in onPause function of your activities.
// This is in your Activity
private ShowToastBroadcastReceiver showToastBroadcastReceiver;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
showToastBroadcastReceiver = new ShowToastBroadcastReceiver();
}
#Override
public void onResume() {
super.onResume();
LocalBroadcastManager.getInstance(this).registerReceiver(showToastBroadcastReceiver, new IntentFilter("SHOW_TOAST"));
}
#Override
public void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(this).unregisterReceiver(showToastBroadcastReceiver);
}
Now you need to send the broadcast from your Service to get the toast to be shown in your Activity.
// This is in your Service
Intent intent = new Intent("SHOW_TOAST");
intent.putExtra("Message", "This toast needs to be shown");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
You should be able to display a Toast from any context, including a Service. The Toast Notifications developer guide has sample code that shows how:
Context context = getApplicationContext();
CharSequence text = "Hello toast!";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
In other words, you don't need an Activity at all. You can display the Toast directly from the Service. If you're worried about doing it from a separate thread, create a Handler in the main thread of the Service and post a Runnable or message to that handler to display the Toast.
One other possibility is that you are using a bound service and it is going away when you switch away from the main activity. Make sure the service itself is still running.
Oh, and also make sure that the 'Show notifications' setting for your app hasn't been unchecked.
Thanks to Reaz I found a stupid error I had made. I was unregistering the BroadcastReceiver handling the Toasts at onStop() instead of onDestroy(). Moving the unregistration to onDestroy() and registration and filters to onCreate() solved the problem.
My Problem:
In MainActivity I start to download some data from the Internet via XML Parser. This data is displayed on every Screen of my App. It is like a Database.
While downloading and saving data, the user of the App can navigate through the hole app. If downloading and saving data is finished, I want to detect and reload the current foreground Activity. I need to do this, to display the new data.
I can detect the current Activity with the ActivityManager and can start it with the ComponentName with the method "startActivity(Intent.makeMainActivity(componentName)". But then the old activity is also there when I navigate back with the ActionBar-BackButton.
I do this in the AsyncTasks onPostExecute-Method after downloading Data.
Any Ideas how to do it?
protected void onPostExecute(MainActivity.UrlParams result) {
Toast.makeText(result.contextMain, "Daten wurden erfolgreich aktualisiert!", Toast.LENGTH_LONG).show();
//Aktualisiert aktive Activity damit die neuen Daten angezeigt werden!
ActivityManager am = (ActivityManager) result.contextMain.getSystemService(ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
Log.d("topActivity", "CURRENT Activity ::" + taskInfo.get(0).topActivity.getClassName());
ComponentName componentInfo = taskInfo.get(0).topActivity;
componentInfo.getPackageName();
Intent intent = Intent.makeMainActivity(componentInfo);
result.contextMain.startActivity(intent);
//myApp.getCurrentActivity().set
}
Download your data is service, not in AsyncTask
Register some BroadcastReceiver in your MainActivity in onStart(), and unregister it in onStop(). Refresh your view in this receiver
When data are downloaded, make a broadcast to call activity, that data are ready.
Disadvantage of this method is that you should save your data somewhere. You can of course pass data in the intent, but only if data are small
I wand a Broadcast receiver invoke when another applications a particular activity is opened in android. For example When Navigation page in Map application that installed in android phone, When opened and showing the Navigation, I want to show a Toast that display "Currently showing Navigation". So how can I achieve that?
This below code will help you to identify windo change event
public class AccessibilityEventService
extends AccessibilityService {
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED)
Log.i("op",event.getPackageName());
}
}
but it has to enabled by users from Accessibility under settings.
or You can check current top activity in a time gap using following code
ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
// get the info from the currently running task
List< ActivityManager.RunningTaskInfo > taskInfo = am.getRunningTasks(1);
Log.d("topActivity", "CURRENT Activity ::"
+ taskInfo.get(0).topActivity.getClassName());
ComponentName componentInfo = taskInfo.get(0).topActivity;
componentInfo.getPackageName();
As my understood that you need to show a toast on onRecieve Fuunction
Toast.makeText(context,"your text",2000).show();
//context is input parameter from onRecieve function
In my app i want to check whethere any other app launches or not from my app.So i am currently usimg Activitymanager to find the top activity like this
ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
List< ActivityManager.RunningTaskInfo > taskInfo = am.getRunningTasks(1);
Log.d("topActivity", "CURRENT Activity ::"
+ taskInfo.get(0).topActivity.getClassName());
ComponentName componentInfo = taskInfo.get(0).topActivity;
componentInfo.getPackageName();
But i want to run this code in background service.So that i can detect When other app launches through this.So is there any idea to do this.Plz help me.thanks
By using service you can achieve this..
public void checkActivity() {
handler = new Handler();
activityRunnable = new ActivityRunnable();
handler.postDelayed(activityRunnable, 500);
}
private class ActivityRunnable implements Runnable {
#Override
public void run() {
ActivityManager manager = (ActivityManager) getApplicationContext()
.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> runningTasks = manager.getRunningTasks(1);
if (runningTasks != null && runningTasks.size() > 0) {
ComponentName topActivity = runningTasks.get(0).topActivity;
// Here you can get the TopActivity for every 500ms
if(!topActivity.getPackageName().equals(getPackageName())){
// Other Application is opened
}
handler.postDelayed(this, 500);
}
}
}
Call the checkActivity() in onCreate of service and dont forgot to remove the handler.removeCallbacks(activityRunnable); callbacks in onDestroy
start the service in LauncherActivity onCreate and stop the service in LauncherActivity onDestroy
Note: Dont forgot to add the permission in your manifest
<uses-permission android:name="android.permission.GET_TASKS" />
You should use Service for this. Then only you can achieve the background process..Please Go through about Services http://developer.android.com/guide/components/services.html and you can see this also http://www.vogella.com/articles/AndroidServices/article.html both URLs will help you
instead of service Use receiver to receive the launch event
and there you can implement this code.
The approach you are taking is wrong and prone to have your app rejected from the Google Play Store (plus it may stop working).
Check this thread to see possible ways to detect wether your app went to the background or not.
I have a broadcast receiver which receives for internet connectivity..and as soon as it doesn't find any connection it opens up my splash activity saying "NO INTERNET CONNECTION"....till now everything is ok but when user put the application into background using device home button and then off the internet connection the splash activity comes to foreground while the app was running in background. I don't want this to happen the splash activity should open but in the background only.
#Override
public void onReceive(Context context, Intent intent) {
// SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean isNetworkDown = intent.getBooleanExtra(
ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
if (isNetworkDown) {
Log.d(TAG, "onReceive: NOT connected, stopping UpdaterService");
Intent myintent=new Intent(context,NoConnectivity.class);
myintent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(myintent);
} else
{
Log.d(TAG, "onReceive: connected, starting UpdaterService");
NoConnectivity.h.sendEmptyMessage(0);
}
}
startActivity will automatically bring the activity to the foreground on top of whicever activity you are viewing. User can go back to the previous one using back button. That's the usual way things work.
However, you can use moveTaskToBack(true) to send your activity to background.
Here is the function description.
EDIT
Check out this question and use the solution to see if your activity is in the background. If yes, then use the method I advised above to send the new activity to the background.
if (isNetworkDown) {
Log.d(TAG, "onReceive: NOT connected, stopping UpdaterService");
// Check the foreground package
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> runningTasks = activityManager.getRunningTasks(1);
ComponentName topActivity = runningTasks.get(0).topActivity;
String foregroundPackageName = topActivity.getPackageName();
if(foregroundPackageName.equals(context.getPackageName()) {
Intent myintent = new Intent(context,NoConnectivity.class);
myintent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(myintent);
}
}