Check if app is open during a GCM onMessage event? - java

I am wondering how to check if my application is open and currently visible to the user when receiving an onMessage() from GCM. At first, I was just using my own boolean isVisible, but then I realized this isn't reliable, because if the app isn't open, the object I use to access that flag is null. While this in itself could be used to see if the app is open, it seems a little bit messy. Is there a way in Android from a system level to somehow check if the application is currently open, and if the user is viewing the app? Keep in mind an app could technically be running, but not be visible, because a user has recently pressed the "home" button sending it to the background.
#Override
protected void onMessage(Context arg0, Intent arg1) {
String turn = intent.getExtras().getString("turn");
if (turn.equals("yours"){
if (/*app is open*/){ <------------------ what can go here?
// dont generate a notification
// display something in the game instead
}
else{
// generate notification telling player its their turn
}
}
}

I would use order broadcasts to do that.
In your onMessage method:
Intent responseIntent = new Intent("com.yourpackage.GOT_PUSH");
sendOrderedBroadcast(responseIntent, null);
In your Activity:
public class YourActivity extends Activity {
final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//Right here do what you want in your activity
abortBroadcast();
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//.....
}
#Override
protected void onPause() {
unregisterReceiver(mBroadcastReceiver);
super.onPause();
}
#Override
protected void onResume() {
IntentFilter filter = new IntentFilter("com.yourpackage.GOT_PUSH");
filter.setPriority(2);
registerReceiver(mBroadcastReceiver, filter);
super.onResume();
}
}
The other BroadcastReceiver
public class SecondReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//In this receiver just send your notification
}
}
Manifest:
<activity
android:name=".YourActivity"
android:label="#string/app_name">
<intent-filter>
<action
android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".SecondReceiver">
<intent-filter
android:priority="1">
<action
android:name="com.yourpackage.GOT_PUSH" />
</intent-filter>
</receiver>
Basically in the onMessage method you send an Intent which is first received by the BroadcastReceiver registered inside YourActivity if it is running and in foreground, otherwise it is received by the SecondReceiver.

Use SharedPreferences saving the boolean isVisible, and when you get the value from the preference you can add a default value.
SharedPreferences settings = context.getSharedPreferences("NAME_XXX", Activity.MODE_PRIVATE);
settings.getBoolean("visible", false);

What I always do is have a reference to the current Activity.
I set the current Activity in every onResume to this and set it to null in every onPause.
If the current Activity is null then the app is not open. If it's not null you can see if the correct Activity is open and deliver it to that Activity.
GCMIntentService:
public static Activity currentActivity;
public static final Object CURRENTACTIVIYLOCK = new Object();
#Override
protected void onHandleIntent(Intent intent) {
synchronized(CURRENTACTIVIYLOCK) {
if (currentActivity != null) {
if (currentActivity.getClass() == CorrectActivity.class) {
CorrectActivity act = (CorrectActivity)currentActivity;
act.runOnUiThread(new Runnable() {
public void run() {
// Notifiy activity
}
});
} else {
// show notification ?
}
} else {
// show notification
}
}
}
CorrectActivity:
#Override
protected void onResume() {
synchronized (GCMIntentService.CURRENTACTIVITYLOCK) {
GCMIntentService.currentActivity = this;
}
}
super.onResume();
}
#Override
protected void onPause() {
synchronized (GCMIntentService.CURRENTACTIVITYLOCK) {
GCMIntentService.currentActivity = null;
}
super.onPause();
}

The thing that worked for me:
Create a final Class Constants, inside it, create static varaiable:
public final class Constants{
public static AppCompatActivity mCurrentActivity;
}
Now, on each on resume of your activties say:
#Override
protected void onResume() {
super.onResume();
Constants.mCurrentActivity = this;
}
When receieving notification, check if current activity is null, if its null, application is not opened, if activity isn't null, you can check things like:
if(Constants.mCurrentActivity instanceof MainActivity){
((MainActivity) Constants.mCurrentActivity).yourPublicMethodOrStaticObject;
}

Related

Making the music play in the background after the app has been closed

My question here is about playing the music after the user closes the app (the app tab is not showing on the list of currently open apps).
I have created a class to handle the service that targets the media player to play the ring-tone music:
public class RingService extends Service {
private MediaPlayer player;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
player = MediaPlayer.create(this,
Settings.System.DEFAULT_RINGTONE_URI);
player.setLooping(true);
player.start();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
player.stop();
}
}
in my MainActivity I use a button to start playing music. And it works fine till I close the app.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onStart() {
super.onStart();
}
public void onRing(View view) {
Intent intent = new Intent(this, RingService.class);
startService(intent);
}
public void onStop(View view) {
Intent intent = new Intent(this, RingService.class);
stopService(intent);
}
}
Is there anyone who could tell me, what I'm doing wrong? I would be extremely grateful.
And just not to start another topic for this app, I will ask it here - is it possible to relaunch the activity in 10 seconds after it has been closed by the user?
I think you missed the onCreate to implement
My app is doing good with this code:
public class BackgroundMusicService extends Service {
MediaPlayer musicPlayer;
public IBinder onBind(Intent arg) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
musicPlayer = MediaPlayer.create(this, R.raw.your_music_file);
musicPlayer.setLooping(true); // Set looping
musicPlayer.setVolume(100,100);
}
public int onStartCommand(Intent intent, int flags, int startId) {
musicPlayer.start();
return 1;
}
#Override
public void onDestroy() {
musicPlayer.stop();
musicPlayer.release();
}
and in you manifest:
<service android:enabled="true" android:name=".BackgroundSoundService" />
So after closing your app you want to play some ringtone using RingService but when user close the app the onStop() method is called in your MainActivity with this code Intent intent = new Intent(this, RingService.class);
stopService(intent);. How service can play your music if you stopping your service at same time.
Try to delete this code from onStop() (not sure it will solve the problem but it worth trying).
Additionally I am recommending using Logcat for testing your code.
https://developer.android.com/studio/command-line/logcat
You need to put your service in foreground with startForeground(id, notification), check the official docs for reference.
When you have a service in foreground, the chances of your process being killed are reduced drastically because your process won't be considered as in background. The downside is that you must show a permanent notification, which in your case might even be desirable because you might need controls for the player.

How to check internet connectivity using broadcast receiver and Change the intent

I am working on an Android application which requires constant listener of Internet connectivity. I am using Broadcast listener and successfully applied it. But my code only shows the Toast message.
I want to stop the current activity and show a default XML file which says "No Internet Connection". and whenever it connect the Internet, previous activity resumes.
ExampleBradcastReceiver.java
public class ExampleBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
boolean noConnectivity = intent.getBooleanExtra(
ConnectivityManager.EXTRA_NO_CONNECTIVITY, false
);
if (noConnectivity) {
Toast.makeText(context, "Disconnected", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, "Connected", Toast.LENGTH_SHORT).show();
}
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
ExampleBroadcastReceiver exampleBroadcastReceiver = new ExampleBroadcastReceiver();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onStart() {
super.onStart();
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(exampleBroadcastReceiver, filter);
}
#Override
protected void onStop() {
super.onStop();
unregisterReceiver(exampleBroadcastReceiver);
}
}
In the place of Toast Message, I want to show a default XML file whenever disconnected and resume activity whenever connected.
You can move ExampleBroadcastReceiver to MainActivity as an inner class. And since in Java inner classes have access to their parent classes' methods and fields, you can in onReceive method consider showing/hiding the Internet disconnected view.
public class MainActivity extends AppCompatActivity {
ExampleBroadcastReceiver exampleBroadcastReceiver = new ExampleBroadcastReceiver();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onStart() {
super.onStart();
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(exampleBroadcastReceiver, filter);
}
#Override
protected void onStop() {
super.onStop();
unregisterReceiver(exampleBroadcastReceiver);
}
private void showInternetDisconnectedView(boolean disconnected){
// show or hide based on 'disconnected'
}
private class ExampleBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
boolean noConnectivity = intent.getBooleanExtra(
ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
showInternetDisconnectedView(noConnectivity);
}
}
}
}
You need to move Broadcast receiver code into Activity and on receiving internet connection events you can stop current in progress activity and make internet failure layout visible there only as it is part of Activity class. If it is required through out the Application, then create Base activity and handle this there to avoid duplicating code on every screen.

background music doesn't stop if app is onStop Android

I have created a service to play music through my activities. I Have 2 activities and a splashScreen. I start the service from the first acitivity and by clicking some items I go to the second activity. The music is played properly but when I put my app in background or I lock my phone or I'm in another app I still hear the sound. I cannot put stopService in onStop because if I go to my second activity, the music will stop.
Here's my service music class :
public class BackgroundMusicService extends Service {
MediaPlayer player;
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
player = MediaPlayer.create(this, R.raw.game_music);
player.setLooping(true);
player.setVolume(10, 10);
player.start();
}
public int onStartCommand(Intent intent, int flags, int startId) {
player.start();
return 1;
}
#Override
public void onDestroy() {
player.stop();
player.release();
}
#Override
public void onLowMemory() {
}
}
and :
public class Activity1 extends AppCompatActivity implements View.OnClickListener{
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_1);
Intent backgSound = new Intent(Activity1.this, BackgroundMusicService.class);
startService(backgSound);
Button b1 = (Button) findViewById(R.id.b1);
b1.setOnClickListener(this);
}
#Override
public void onDestroy() {
super.onDestroy();
Intent backgSound = new Intent(Activity1.this, BackgroundMusicService.class);
stopService(backgSound);
}
#Override
public void onClick(View v) {
startActivity(new Intent(this,Activity2.class);
}
And the second activity is just a view (for test).
How could I keep the sound over these 2 activites and stop it when my app is in background or my phone is locked.
I've tried to stopService in onStop then startService in onResume, but it does not work between activities.
Judging by what you want you need a more fine grained control over the starting and stopping of your MediaPlayer object. An easy solution would be to add intent-filters and actions like so:
public class BackgroundMusicService extends Service {
public static final String ACTION_START_MUSIC = "package_name.action_start_music";
public static final String ACTION_STOP_MUSIC = "package_name.action_stop";
private MediaPlayer player;
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
player = MediaPlayer.create(this, R.raw.game_music);
player.setLooping(true);
player.setVolume(10, 10);
}
public int onStartCommand(Intent intent, int flags, int startId) {
if(intent.getAction() != null){
switch (intent.getAction()){
case ACTION_START_MUSIC :
if(!player.isPlaying()){
player.start();
}
break;
case ACTION_STOP_MUSIC :
if(player.isPlaying()) {
player.stop();
}
break;
default: break;
}
}
return START_STICKY;
}
#Override
public void onDestroy() {
player.release();
}
#Override
public void onLowMemory() {
}
}
Update your manifest :
<service android:name=".BackgroundMusicService"
android:exported="false">
<intent-filter>
<action android:name="package_name.action_start_music" />
<action android:name="package_name.action_stop" />
</intent-filter>
</service>
To use:
startService(new Intent(BackgroundMusicService.ACTION_START_MUSIC));
startService(new Intent(BackgroundMusicService.ACTION_STOP_MUSIC));
It is well known that onDestroy() is not always calling, moving your onDestroy actions to the onPause() method will work:
Note: do not count on this method being called as a place for saving data! For example, if an activity is editing data in a content provider, those edits should be committed in either onPause() or onSaveInstanceState(Bundle), not here. This method is usually implemented to free resources like threads that are associated with an activity, so that a destroyed activity does not leave such things around while the rest of its application is still running. There are situations where the system will simply kill the activity's hosting process without calling this method (or any others) in it, so it should not be used to do things that are intended to remain around after the process goes away.
More info here.
You need to read more about the basics of Android.
Regards.

Add list item in RecyclerView Adapter on receiving Firebase message

I'm using the firebase messaging service for messaging and notifications. I can't seem to be able to pass an incoming message from the service to the adapter so that when the message is received it can be inserted into the RecycleView List.
I tried using BroacastIntent as follows :
public class messaging extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage m) {
store(m.getData());
broadcastIntent();
}
public void broadcastIntent() {
Intent intent = new Intent();
intent.setAction("com.myApp.CUSTOM_EVENT");
sendBroadcast(intent);
}
}
and in the Adpter
public class ConvoAdapter extends RecyclerView.Adapter<ConvoHolder> {
private List<Message> list;
private Activity A;
public ConvoAdapter(List<Message> data) {
}
#Override
public ConvoHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(layout, parent, false);
return new ConvoHolder(v);
}
#Override
public void onBindViewHolder(ConvoHolder h, int Position) {
final Message M = list.get(Position);
h.config(A, M);
}
#Override
public int getItemCount() {
return list.size();
}
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Intent Detected.", Toast.LENGTH_LONG).show();
}
}
}
And manifest.
<receiver android:name=".fragments.chats.ConvoAdapter$MyReceiver"
android:enabled="true"
android:exported="false" >
<intent-filter>
<action android:name="android.intent.action.CUSTOM_EVENT">
</action>
</intent-filter>
</receiver>
As is, the broadcast receiver is not receiving any messages.
I'd also use any other method that doesn't involve using broadcast receivers.
The flow or architecture of your is not a standard practice.
The standard flow should be
Firebase service
Some activity or fragment with BroadcastReceiver using LocalBroadcastManager
1. Firebase Service
public class messaging extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage m) {
store(m.getData());
broadcastIntent();
}
public void broadcastIntent() {
Intent intent = new Intent();
intent.setAction("com.myApp.CUSTOM_EVENT");
// We should use LocalBroadcastManager when we want INTRA app
// communication
LocalBroadcastManager.getInstance(YOUR_CONTEXT).sendBroadcast(intent);
}
}
2. Activity
Registering Receiver for broadcast from Service
public void onCreate(Bundle savedInstance) {
// REST OF YOUR CODE
IntentFilter if= new IntentFilter("com.myApp.CUSTOM_EVENT");
LocalBroadcastManager.getInstance(this).registerReceiver(onMessage, if);
}
Writing the Receiver in Activity
private BroadcastReceiver onNotice= new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Update your RecyclerView here using notifyItemInserted(position);
}};
Summary: The Service sends local broadcast to Activity which in turn receives it and updates or add items using RecyclerView instance
if in case you don't want to use BroadCaseReceiver for your task.Follow below steps:
There are two things to note here.
Firstly,Check whether the Activity is open(Activel visible) or not.
i. When your screen is active.(screen is visible).
1.In your onMessageReceived() store the received message in SQLiteDataBase with time.
2.create a method in your adapter which will update the screen by fetching the data from SQLiteDB.
3.Now whenever a new message is received call this method in Adapter class.
ii.in case the screen is not active:
1.store the received message in sqliteDb and show it as a notification.
note:
1.make sure you write all these in a try catch block.
2.make sure to sync your SQLiteDB on opening the screen for the first time.
3.in case if this does not help you please try this way.. Refreshing activity on receiving gcm push notification
I think the above code didnt worked because the action name above given and the one registered in manifest is different
<action android:name="com.myApp.CUSTOM_EVENT">
</action>
intent.setAction("com.myApp.CUSTOM_EVENT");
give same name i think the above code will work

Showing activity from onCreate

Problem Description
I have two activities in my application MainActivity and BannerActivity. From the main activity I start BannerActivity in onCreate method. But I first I see MainActivity screen for a second and then BannerActivity screen.
Question
How I can do so that BannerActivity will be shown first and after countdown timer will stop and BannerActivity will close after that MainActivity come to the screen.
MainActivity
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/* Show banner activity for several seconds then close it. */
Intent bannerIntent = new Intent(MainActivity.this, BannerActivity.class);
this.startActivity(bannerIntent);
}
};
BannerActivity
public class BannerActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
/* Make banner fullscreen. */
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_banner);
/* Launch count down timer for several seconds. */
CountDownTimer countDownTimer = new CountDownTimer(3000, 1000) {
#Override
public void onTick(long millisUntilFinished) { /* Not used. */ }
#Override
public void onFinish() {
BannerActivity.this.finish();
}
}.start();
}
#Override
public void onBackPressed() {
/* Lock back button presses. */
super.onBackPressed();
}
};
You need a SplashScreen:
http://www.thiagorosa.com.br/en/tutorial/part01-splash-screen
public class GameSplash extends Activity {
// time to wait on the splash screen
private static final int SPLASH_SCREEN_DELAY = 3000;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
new Thread() {
#Override
public void run() {
try {
// do any heavy initialization here
// wait a few seconds before going to the next screen
sleep(SPLASH_SCREEN_DELAY);
}
catch (InterruptedException e) {
}
catch (Exception e) {
}
finally {
// start the level selection screen
Intent intentSelect = new Intent(GameSplash.this, GameSelect.class);
startActivity(intentSelect);
}
}
}.start();
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// ignore any key press on the splash screen
return true;
}
}
Run first BannerActivity and in the contdown run MainActivity rather than BannerActivity.this.finish();
You can start with BannerActivity and then when the time expires you go to MainActivity and clear the history stack by using this intent flag (so that you can't go back to the BannerActivity using the back button).
Intent.FLAG_ACTIVITY_CLEAR_TASK
Swap the activites on the Manifest to decide which activity is run first :
<activity
android:name="com.yourpackagename.MainActivity"
android:label="#string/app_name" >
</activity>
<activity
android:name="com.yourpackagename.BannerActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
The BannerActivity should have the <intent-filter> tag and set as Main and Launcher as the example. This will make Banner activity as the Initial Activity when you start your application.
After that you can just implement countdowntimer and start MainActivity when the timer ends.
Hope this helps, Good Luck ^^
try to use this way first need to load xml layout
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_banner);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
or try to put in manifest like
<activity
android:name=".BannerActivity"
android:label="#string/app_name"
android:theme="#android:style/Theme.NoTitleBar.Fullscreen"
>
you can do like this also in your Banner Activity
use this code in oncreate method in banner activity
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
finish();
}
}, 2000);
You need splash screen. Try this:
Start BanerActivity first. And make its onCreate like
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Thread welcomeThread = new Thread() {
int wait = 0;
#Override
public void run() {
try {
super.run();
while (wait < 5000) { //Wait of 5 seconds
sleep(500);
wait += 500;
}
} catch (Exception e) {
} finally {
Intent i = new Intent(BanerActivity.this,
MainActivity.class);
startActivity(i);
finish();
}
}
};
welcomeThread.start();
}
Hope this helps.
the easiest solution is to make the BannerActivity the launcher activity and modify the CountDownTimer to be
#Override
public void onFinish()
{
Intent mainIntent = new Intent(this, MainActivity.class);
startActivity(mainIntent);
finish();
}
then adjust the manifest file to make the BannerActivity as the launcher activity and remove it from the MainActivity

Categories