I have an Activity which looks up data from the web in its onCreate method. The Activity is activated by the user hitting a notification. So it is a common problem that the user will quickly turn on their phone, unlock it, slide open notifications, tap the notification, and the Activity will activate before the phone is done connecting to internet.
I do have a friendly AlertDialog that pops up informing the user that the data couldn't be received and to try again when the network is connected; but is there a way for the Activity to actively tell the phone to connect and detect that a connection is being made and then wait for the connection to establish, and then load its data successfully?
Usually, you would do something like this:
#Override
public void onResume(){
super.onResume();
// first, check connectivity
if ( isOnline ){
// do things if it there's network connection
}else{
// as it seems there's no Internet connection
// ask the user to activate it
new AlertDialog.Builder(YourActivity.this)
.setTitle("Connection failed")
.setMessage("This application requires network access. Please, enable " +
"mobile network or Wi-Fi.")
.setPositiveButton("Accept", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// THIS IS WHAT YOU ARE DOING, Jul
YourActivity.this.startActivity(new Intent(Settings.ACTION_WIRELESS_SETTINGS));
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
YourActivity.this.finish();
}
})
.show();
}
}
The idea is ask the user to go and configure a network connection. Then, if the user does want to configure it, you will call the Settings.ACTION_WIRELESS_SETTINGS intent.
Also, notice the isOnline variable, which is a boolean that tells whether there's a network connection or not. In order to set that variable you can use an external simple class like this:
public class CheckConnectivity {
public static boolean isOnline(Context context) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if( cm == null )
return false;
NetworkInfo info = cm.getActiveNetworkInfo();
if( info == null )
return false;
return info.isConnectedOrConnecting();
}
}
Also, you will have to add this permission to your AndroidManifest.xml file:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
From this last statement by Cristian
'return
info.isConnectedOrConnecting();' It seems you can do whatever you want to do with the activity based on the boolean value returned by the method.
Since what you after is a positive return value you can use it's variable to callback your activity's next action
Related
So I'm working for a company that requires a VPN in order to connect to the database server. I'm facing an issue with disconnecting programmatically from the VPN service (or disabling it) upon onPause / onStop.
In order to ensure the user is indeed connected to a VPN, I'm using a network listener and if the user is not connected, a dialog is being shown and navigates the user to the VPN Settings Configuration. Once the user connects and resumes the application, the listener recognizes the VPN IP and everything runs great.
My issue is that I want to disable the VPN connection once the user has stopped using the application. Therefore, I've been trying to search for a solution that disables the VPN connection without requesting the user to go to the VPN Settings again. Is there an option to toggle the VPN off programmatically without navigating to the VPN Settings page?
Network Service:
public class NetworkSchedulerService extends JobService implements
ConnectivityReceiver.ConnectivityReceiverListener {
private ConnectivityReceiver mConnectivityReceiver;
#Override
public void onCreate() {
super.onCreate();
mConnectivityReceiver = new ConnectivityReceiver(this);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}
#Override
public boolean onStartJob(JobParameters params) {
registerReceiver(mConnectivityReceiver, new IntentFilter(Constants.CONNECTIVITY_ACTION));
return true;
}
#Override
public boolean onStopJob(JobParameters params) {
unregisterReceiver(mConnectivityReceiver);
return true;
}
#Override
public void onNetworkConnectionChanged(boolean isConnected) {
String message = isConnected ? "מחובר לרשת" : "אין חיבור פעיל לרשת";
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
}
}
Listener:
private void scheduleJob() {
JobInfo myJob = new JobInfo.Builder(0, new ComponentName(this, NetworkSchedulerService.class))
.setRequiresCharging(true)
.setMinimumLatency(1000)
.setOverrideDeadline(2000)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.setPersisted(true)
.build();
JobScheduler jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
jobScheduler.schedule(myJob);
}
#Override
protected void onStop() {
stopService(new Intent(this, NetworkSchedulerService.class));
super.onStop();
}
#Override
protected void onStart() {
super.onStart();
Intent startServiceIntent = new Intent(this, NetworkSchedulerService.class);
startService(startServiceIntent); // INTERNET LISTENER
}
Dialog:
public void dialogVPN() {
builder = new AlertDialog.Builder(LoadingSplash.this);
builder.setMessage("Please ensure VPN Connection");
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent("android.net.vpn.SETTINGS");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivityForResult(intent, 10);
}
});
builder.show();
}
And the returnConnType:
public String returnConnType() {
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(this.CONNECTIVITY_SERVICE);
String result = "None";
if (connectivityManager != null) {
Network network = connectivityManager.getActiveNetwork();
NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(network);
if (capabilities == null) {
result = "None";
}
if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
result = "WIFI";
} else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
result = "MOBILE";
} else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
result = "VPN";
}
}
return result;
}
Any suggestions as to how to solve this? A proper solution or an alternative one would be appreciated.
I don't think you can disable the VPN settings from inside the app using an API provided by Android, as I do not know about any such APIs. However, as a workaround, you can consider doing the following.
While exiting the application (on a back button press), you can use the same listener to pop up another dialog saying the user to turn off the VPN. Hence, turning off the VPN will follow the same tasks that the user had to do while turning on the VPN.
When a user exits the application using a home button press, you might consider using a JobScheduler in your onDestroy function of the exiting activity, so that you can check if the VPN connection is alive in a background service when the application is not running and create a notification which will tell the user that, the VPN is alive. Then on clicking the notification, redirect the user to the VPN configuration settings and guide the user to turn it off.
Hope that helps!
So thanks to #Reaz I've managed to find the proper solution for now.
Tested on Oreo
In case someone else is intrested..
app
implementation 'android.arch.lifecycle:extensions:1.1.1'
AppLifecycleObserver
public class AppLifecycleObserver extends MultiDexApplication implements LifecycleObserver {
public static final String TAG = AppLifecycleObserver.class.getName();
Notifications notif = new Notifications();
Context mContext;
public AppLifecycleObserver(Context context) {
mContext = context;
}
#OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onEnterForeground() {
Log.v(TAG,"FOREGROUND");
}
#OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onEnterBackground() {
Log.v(TAG,"BACKGROUND");
notif.createVPNNotification(mContext,"VPN","Please make sure to turn VPN off");
}
}
on Any activity you wish to implement # onCreate:
AppLifecycleObserver appLifecycleObserver = new AppLifecycleObserver(this);
ProcessLifecycleOwner.get().getLifecycle().addObserver(appLifecycleObserver);
I am working on a messaging app, it sends user notification when he is on a different activtyon my app or is on another app but if the user is on MessagingActivity.java it just updates the chat history and does not send any notifications which is perfectly fine, but the problem arises when the user is on MessagingActivity.java meanwhile an email or something else happen user leaves the MessagingActivity.java open and checks that app if in the meantime a message comes user does not receive any notifications
public void parseRequest(Bundle extras) {
if (extras.containsKey("for") && extras.containsKey("recipientID")) {
if (Integer.parseInt(extras.getString("recipientID")) == M.getID(this)) {
switch (extras.getString("for")) {
case "chat":
if (isRunning("MessagingActivity")) {
Intent intent = new Intent("update_messages_list");
intent.putExtra("data", extras);
sendBroadcast(intent);
} else {
Intent resultIntent = new Intent(this, MessagingActivity.class);
resultIntent.putExtra("conversationID", Integer.parseInt(extras.getString("conversationID")));
resultIntent.putExtra("recipientID", Integer.parseInt(extras.getString("ownerID")));
M.showNotification(getApplicationContext(), resultIntent,
extras.getString("ownerUsername"),
extras.getString("message"),
Integer.parseInt(extras.getString("conversationID")));
}
Let me know how you are checking that your MessageActivity is Running i.e. functioning of isRunning("MessagingActivity") method. If you are setting any global boolean variable for checking this and making isRunning value false in onDestroy() method of that activity then, according to life cycle of Activity it is not called until your activity is finished i.e. in your case user just switching from MessageActivity to Mail .
I am by no means an expert, but you could just set a boolean variable by overriding the Activity's onPause() and onResume() events.
Simply set msgActivityActive to true in onResume(), false in onPause(), and change your call to:
if (isRunning("MessagingActivity") && msgActivityActive)
I need my application to give a notification whenever a specific WiFi goes offline.
I got it to give a notification every time the WiFi connection disconnects. But I need it to only give a notification when a specific WiFi network disconnects. Is my code suitable for this? I read something about class wifiinfo, is this the solution?
My question is, how do I alter the code to only give a notification when a specific WiFi goes offline? Any help in the right direction would be nice! Some examples would be even more awesome.
Thanks in advance!
(Eventually I need a button and when you press this the specific wifi your on atm will become that specific wifi when you disconnect from it you get a notification. If that makes sense.)
The code:
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
this.registerReceiver(this.mConnReceiver,
new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
setContentView(R.layout.activity_hoofdmenu);
}
private BroadcastReceiver mConnReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
if(!isNetworkConnectionAvailable(context)){
showNotification();
}
}
};
public static boolean isNetworkConnectionAvailable(Context context)
{
boolean isNetworkConnectionAvailable = false;
ConnectivityManager connectivityManager = (ConnectivityManager)context.getSystemService("connectivity");
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
if(activeNetworkInfo != null)
{
isNetworkConnectionAvailable = activeNetworkInfo.getState() == NetworkInfo.State.CONNECTED;
}
return isNetworkConnectionAvailable;
}
To detect SSID changes, listen for WifiManager.NETWORK_STATE_CHANGED_ACTION, grab the SSID from the intent extra WifiManager.EXTRA_BSSID.
See: Execute code when wifi SSID changes
I have a service and application. There is communication between them by sending intents on specific situations. In activity I register and unregister broadcast receiver to collect this intents. Intents from service are sending when particular callback method is executed. Is there a possibility to send this intents only when activity is in the foreground? Because when this is hide there is no need to gather this intents (it helpful only to show some situations in real time)? I figure out that in activity could be static field that indicates about such situation, but I don't know how to get access to activity from service and additionally I found information that this is vary bad design practise.. Thank for any suggestions!
Declare this in your Activity:
public static boolean isRunning;
Then in your onPause to set isRunning = false;
and in onResume set it to isRunning = true;
Then from your Service you can simply call ActivityName.isRunning to know if it is in foreground or not!
you can use a static variable within the activity.
class MyActivity extends Activity {
static boolean active = false;
#Override
public void onStart() {
super.onStart();
active = true;
}
#Override
public void onStop() {
super.onStop();
active = false;
}
}
Add just check in service as
if(MyActivity.active)
{
//send broadcast.
}
OR
go with this to check status of activity is it active or not
public boolean isRunning(Context ctx) {
ActivityManager activityManager = (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> tasks = activityManager.getRunningTasks(Integer.MAX_VALUE);
for (RunningTaskInfo task : tasks) {
if (ctx.getPackageName().equalsIgnoreCase(task.baseActivity.getPackageName()))
return true;
}
return false;
}
I'd have a local boolean variable in service:
protected boolean mIsAppRunning;
Call startService() with true/false extra when app resumes/stops:
#Override
protected void onResume() {
super.onResume();
Intent service = new Intent("my.service.ACTION");
service.putExtra("IS_MY_ACTIVITY_RUNNING", true);
startService(service);
}
#Override
protected void onPause() {
Intent service = new Intent("my.service.ACTION");
service.putExtra("IS_MY_ACTIVITY_RUNNING", false);
startService(service);
}
Check that extra in service's onStartCommand() and assign its value to mIsAppRunning:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null) {
mIsAppRunning = intent.getBooleanExtra("IS_MY_ACTIVITY_RUNNING", false);
}
return START_STICKY;
}
If you design the logic in the service a little carefully, you may even get rid of the local variable, mIsAppRunning, and call the required methods depending on the intent extra value.
Hope this helps.
This question already has answers here:
Check INTENT internet connection
(13 answers)
Closed 3 months ago.
I am working on an Android app that will continuously remain connected to Internet. If Internet is dow, it should give an appropriate message to the User.
Is there any thing like Internet Listener? Or how to implement this event that whenever Internet connection is not available it should give alert.
The code from Chirag Raval above certainly works. The trouble is that the listener will get invoked even when the application is not running in foreground.
IMHO, the better approach is to register / unregister the receiver in the onResume() / onPause() methods of all your application activities. This code should do it:
private final NetworkStateReceiver stateReceiver = new NetworkStateReceiver();
#Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter();
filter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
registerReceiver(stateReceiver, filter);
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(stateReceiver);
}
Obviously, remove the registration from AndroidManifest.xml file.
Using this solution, the receiver will be called also when switching between activities of your application (assuming you are closing them). In such a case, use a static flag (being shared between all your activities) like in the example below (called online):
public class NetworkStateReceiver extends BroadcastReceiver {
private static boolean online = true; // we expect the app being online when starting
public static final String TAG = NetworkStateReceiver.class.getSimpleName();
public void onReceive(Context context, Intent intent) {
Log.d(TAG,"Network connectivity change");
ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo ni = manager.getActiveNetworkInfo();
if (ni == null || ni.getState() != NetworkInfo.State.CONNECTED) {
Log.d(TAG,"There's no network connectivity");
if (online) // don't show the message if already offline
Toast.makeText(context, R.string.noInternet, Toast.LENGTH_SHORT).show();
online = false;
} else {
Log.d(TAG,"Network "+ni.getTypeName()+" connected");
if (!online) // don't show the message if already online
Toast.makeText(context, R.string.backOnline, Toast.LENGTH_SHORT).show();
online = true;
}
}
}
If starting your app when being offline, the Toast message will appear; otherwise it appears only when losing / re-establishing the connection .