I have an AlertActivity and an Activity. When a broadcast is received, both activities needs to finish. But the below code results Black screen if AlertActivity is on top of Activity.
Below is the code in Activity:
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals("BROADCAST_INTENT")){
if(alertActvity != null)
alertActivity.finish();
finish();
}
}
And code in AlertActivity:
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals("BROADCAST_INTENT"))
finish();
}
}
First, Activity's onStop() is getting called before AlertActivity's onStop() is called which results in Black screen, even AlertActivity's finish() called before Activity's finish().
Please help me in this regard.
Finally, I found a solution for this:
Finishing an Activity with a delay of 1 second which really works. By that time, AlertActivity finishes and black screen cannot be displayed.
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
finish();
}
}, 1000);
as in both AlertActivity and Activity, you are checking for same action "BROADCAST_INTENT", I assume you registered both receiver in their own class.
If you did so, then actually you have two broadcast receiver waiting for same event. when this event occurs, both of your receiver are going to get it.
So in your AlertActivity is getting finished twice.
I think #Amit K. Saha, is right, your AlertActivity may be finishing twice
Solution :
If your application is running >= API 16 then you can use finishAffinity() method :
Finish this activity as well as all activities immediately below it in the current task that have the same affinity. This is typically used when an application can be launched on to another task (such as from an ACTION_VIEW of a content type it understands) and the user has used the up navigation to switch out of the current task and in to its own task. In this case, if the user has navigated down into any other activities of the second application, all of those should be removed from the original task as part of the task switch.
Note that this finish does not allow you to deliver results to the
previous activity, and an exception will be thrown if you are trying
to do so.
You can call finishAffinity() from AlertActivity because it is on top of Activity. This will finish AlertActivity as well as Activity
My transparent Activity finish results black screen, after a search, i find it is caused by activity switching animation in Android 4.4. But above android 5.1 the phenomenon does not show up.
So I add the below code:
#Override
public void finish() {
super.finish();
overridePendingTransition(0, 0);
}
The black screen after finish is gone.
I think this may be helpful.
try this
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals("BROADCAST_INTENT"))
context.finish();
}
}
Related
I'm struggling with this issue and I want to know if there is any option to know why an activity is being closed, I have checked if it was a low memory issue with Runtime.getRuntime().freeMemory(); but everything looks fine.
UPDATE
Here is how I call the activities and when suddenly all the background activities are closed. In all the way from MainActivity to SketchActivity I'm not calling the finish(); method but when I start the SketchActivity from BoulderProfileActivity, all the activies are destroyed, except SketchActivity :
MainActivity:
private void SendUserToFindBoulderActivity(){
Intent boulderFindIntent = new Intent(MainActivity.this, FindBouldersActivity.class);
startActivity(boulderFindIntent);
}
FindBouldersActivity:
holder.mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent boulderProfileIntent = new
Intent(FindBouldersActivity.this,BoulderProfileActivity.class);
boulderProfileIntent.putExtra("BoulderKey", BoulderKey);
startActivity(boulderProfileIntent);
}
});
BoulderProfileActivity:
public void SendUserToSketchUpActivity(){
Intent sketchIntent = new Intent(BoulderProfileActivity.this, SketchActivity.class);
sketchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
if(sustituir==false) {
sketchIntent.putExtra("BoulderKey", BoulderKey);
sketchIntent.putExtra("Uri", ImageUri);
sketchIntent.putExtra("sustituir", sustituir);
}else{
sketchIntent.putExtra("BoulderKeyForSwitchFirstImage", BoulderKey);
sketchIntent.putExtra("Uri", ImageUri);
sketchIntent.putExtra("photoKey", photoKey);
sketchIntent.putExtra("sustituir", sustituir);
}
startActivity(sketchIntent);
}
When you start SketchActivity you are using flags
sketchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
and these flags close all previous activities and start the activity in a new task.
so to keep old previous activities please remove this line.
if you don't know what is a task, the task is the container for activities, so when you start new task this means that the activity is the first activity if you want to read more about tasks follow this link :
https://developer.android.com/guide/components/activities/tasks-and-back-stack
and you can find more information about intent flags here
https://developer.android.com/reference/android/content/Intent#FLAG_ACTIVITY_CLEAR_TASK
Any chance you enabled developer mode (System -> Developer options), and it is force-closing the Activity?
There's an option (Developer Options, under 'apps', I'm using a Pixel 3) called 'Don't keep Activities' which should be disabled.
I've implemented something similar to Android notification of screen off/on, but it's not working the way it should. All I want to do is stop music when the screen is turned off. I created a screen action class like this
public class ScreenAction extends BroadcastReceiver {
public static boolean wasScreenOn = true;
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
// DO WHATEVER YOU NEED TO DO HERE
wasScreenOn = false;
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
// AND DO WHATEVER YOU NEED TO DO HERE
wasScreenOn = true;
}
}
}
Then, in my main activities on create I have this
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
BroadcastReceiver mReceiver = new ScreenAction();
registerReceiver(mReceiver, filter);
In my main activities onPause, I have something like this:
public void onPause() {
super.onPause();
if (ScreenAction.wasScreenOn) {
final MediaPlayer mp = MediaPlayer.create(this, R.raw.pcmouseclick1);
mp.setVolume(.1f, .1f);
mp.start();
if (buttonState) {
mServ.reduceVolume();
}
}
}
I found this from an online source, but I am having issues. It seems that the screen state is always set as true, and I'm not sure how to change this.
How do I utilize this ScreenAction class to turn off music in on Pause ONLY when the user has locked the screen? I feel like I am missing something in the onPause because in onCreate I link to the class.
#Override
protected void onPause() {
// when the screen is about to turn off
// or when user is switching to another application
super.onPause();
}
#Override
protected void onResume() {
// only when screen turns on
// or when user returns to application
super.onResume();
}
Here you can see the entire lifecycle of an Activity in android:
Activity Lifecycle
Maybe you could also start and stop your music directly from the receiver:
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
// Pause music player
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
// Resume music player
}
}
You're checking ScreenAction.wasScreenOn in onPause, but that's happening before the BroadcastReceiver is called to notify you that the screen is being turned off. So at that point, ScreenAction.wasScreenOn is still true, and then it's set to false, but onPause has already run, so your music never gets paused.
To solve this, you should take the action directly in response to the screen turning off in the BroadcastReceiver. If you need to interact with your UI, consider a solution like LiveData as an abstraction so that you're not reliant on your Activity being paused at the exact moment the screen is turned off (consider also that the onPause solution wouldn't work if your Activity weren't currently visible).
I have a, what I thought was a, simple task. I have a list of achievements in a recyclerView in my MainActivity. Clicking on one of the achievements launches the AchievementDetailActivity. You do an action in the AchievementDetailActivity and it completes the achievement. When that happens, I need the thumbnail on the MainActivity to be the achievement icon and not the locked icon. What I thought was I could just use the LocalBroadcastManager to send and receive messages from one activity to another, but that isn't working. From everything I have read you are supposed to unregister the listener in your activity onPause and onStop lifecycle methods, however, if you unregister the listener in the onPause of MainActivity, it gets unregistered when the AchievementDetailActivity starts and nothing gets delivered to the MainActivity. I don't understand how you can use LocalBroadCastManager with receivers to send information between activities when they get unregistered as soon as you start a new activity. The following example shows it unregisters as soon as the second activity is started, so the first activity will never get the broadcast...
public class MainActivity extends AppCompatActivity {
public static final String ACTION = "update";
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("MAIN ACTIVITY", "RECEIVED EVENT");
}
}
public void onStart() {
super.onStart();
LocalBroadcastManager.getInstance(this).registerReceiver(receiver), new IntentFilter(ACTION));
}
public void onPause() {
Log.d("MAIN ACTIVITY", "REMOVING LISTENER");
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
}
//.. The rest of MainActivity
}
public class SecondActivity extends AppCompatActivity {
#Override
public void onStart() {
super.onStart();
//initialize view and such
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getApplicationContext());
Intent intent = new Intent(MainActivity.ACTION);
intent.putExtra("Something", "somewhere");
manager.sendBroadcast(intent);
}
)};
}
If you run the above, obviously with the buttons and such, you will get a message that shows it unregisters the listener as soon as SecondActivity starts and the MainActivity will never get the message it is supposed to get when you click a button on the second activity.
Is there a way to send information from activity to activity, or because of the lifecycle events is that not possible? Everything I read said LocalBroadcastManager was the right way to do it, but it gets unregistered so, how can it? Please help, this is driving me nuts. Thank you.
If you want to use your LocalBroadcastManager to fetch results, do not unregister in onPause, in which case must to unregister in onDestroy().
If you startAvtivity only to fetch some results, it is a good way to startActivityForResult.
Its not a great idea to use LocalBroadcastReceiver for this purpose. Use startActivityForResult instead. Follow this Official doc for implementation details.
The reason its not wokring is:
You are registering the receiver in onStart and unregistering it in onPause(). When your second activity is shown, onPause () will be called as a result the BroadcastReceiver is unregistered.
Its not a great idea to keep it registered since it would lead to memory leaks.
I am writing my code in Android Studio, but the project that I am writing has no GUI, and never updates views for a user. It simply listens for the last installed app with a Broadcast Receiver and sends info to another java file.
I am wondering how I can send a string from a broadcast receiver to an activity (maybe this should not be an "activity" but a "service"?), and have this work while the app is in the background.
Right now I have a broadcast receiver listening for the last installed app on my phone (this runs in the background). And I have a custom broadcast receiver set up to notify my main activity when the broadcast receiver gets an installed app. But this custom receiver doesn't work in the background. Again, maybe I shouldn't be using an Activity to receive info from the BroadcastReceiver?
Is there a way I can send information from my broadcast receiver to my main activity while the app is in the background? I also need my main activity to resume normal function while in the background (there are no GUI updates done while it's in the background).
My BroadcastReceiver which is sending data to my Main Activity through a new Intent
public class NewInstallReceiver extends BroadcastReceiver {
ApplicationInfo ai;
#Override
public void onReceive(Context context, Intent intent) {
final PackageManager pm = context.getPackageManager();
try {
// if app is added, get package info
ai = pm.getApplicationInfo(intent.getData().getSchemeSpecificPart(), 0);
Intent i = new Intent("broadcastName");
// Data pass to activity
i.putExtra("appInfo", ai);
context.sendBroadcast(i);
} catch (final PackageManager.NameNotFoundException e) {
ai = null;
}
}
}
In my MainActivity in onCreate I register the receiver:
registerReceiver(broadcastReceiver, new IntentFilter("broadcastName"));
I receive data from BroadcastReceiver
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// get applicationInfo
Bundle b = intent.getExtras();
Object applicationInfo = b.get("appInfo");
ApplicationInfo appInfo = (ApplicationInfo) applicationInfo;
getNewData(appInfo);
}
};
Then I have to unregister the receiver in MainActivity, but obviously this doesn't allow for me to receive info from BroadcastReceiver once the app goes in the background
#Override
public void onStop()
{
try{
unregisterReceiver(broadcastReceiver);
}
catch(Exception e){
System.out.println("Exception is " + e.toString());
}
super.onStop();
}
Honestly, I don't think that update an Activity that is in background is a good practice (even if possible).
According to DOCS:
An activity is a single, focused thing that the user can do. Almost all activities interact with the user, so the Activity class takes care of creating a window for you in which you can place your UI with setContentView(View). While activities are often presented to the user as full-screen windows, they can also be used in other ways: as floating windows... or embedded inside of another activity (using ActivityGroup).
So, if the Activity is in background, it does not visible. So, it is useless to update its contents (because it is not visible to user).
In fact, you should implement following behavior instead:
Use your Service only to save the information (in a database/content provider) and to notifies the Activity that a new information is available. Then, if your activity is open, it immediately consumes that information. If Activity is not opened, the info remains saved for when the user needed it.
If app was only stopped, you can update the Activity content during onResume() method.
If your app was killed and user opened it again, you can update ALL Views during onCreate() method. onCreate() is called before the View is displayed to user.
This way, the info will be updated when needed: when the user wan's to check the info. Otherwise, it is a waste of time.
I have a service that is, among other things, downloading images from internet. When this is done I want to show this image in a custom Activity that has a dialog theme. But I only want to use this pop up if the app is running, otherwise I just want to create a notification.
But I get an exception when I try to start an activity from my service and i feel that maybe this isn't the right way to do it?
It says:
android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
So my question is if this is the right way to do this by setting that flag or how should I get my downloaded image from my service to an activity. Can I in some way tell an activity to start a new activity from my service class?
I think using Broadcast Receiver is better option for you.
Add Below Method in Service and call this method when image Download Complete.
private void updateMyActivity(Context context) {
if(MainActivity.activityStatusFlag){
//update the activity if activityStatusFlag=true;
Intent intent = new Intent("mUpdateActivity");
context.sendBroadcast(intent);
}else{
//display notification if activityStatusFlag=false;
}
}
In Activity Add Following Code.
public class MainActivity extends Activity{
public static boolean activityStatusFlag= false;
//define this variable to check if activity is running or not.
#Override
protected void onResume() {
super.onResume();
activityStatusFlag = true;
this.getApplicationContext().
registerReceiver(mMessageReceiver,new IntentFilter("mUpdateActivity"));
}
#Override
protected void onPause() {
super.onPause();
activityStatusFlag = false;
this.getApplicationContext().unregisterReceiver(mMessageReceiver);
}
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//Display Popup or update Activity
}
};
}