In the OnResume method of my fragmentActivity i try to:
Check if an internet connection is available, if not display a FragmentDialog
if the var storeId id is set to 0, call a new activity whose ask for the id
display the activity
Here is my code:
#Override
protected void onResume() {
super.onResume();
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
if (connectivityManager.getActiveNetworkInfo() ==null){
noConDialog.show(getFragmentManager(), NET_ALERT_DIALOG);
Log.e("jedois","pas m'afficher");
}
if (storeId == 0) { //si on a plus la boutique id
//call logon activity
Intent logonActivity = new Intent(ShoppingActivity.this, LogonStoreActivity.class);
startActivityForResult(logonActivity, LOGON_STORE_REQUEST);
}
}
The problem is, after execute the lines "noConDialog.show(getFra..."the dialog appear but on resume execute the other line to, the my second activity start and hide my dialog.
A dialog is modal, then the app must wait the end of the Dialog, before execute the other lines . Right?
Thanks for your help
Return from the method after calling the dialog.show().
The code will not terminate unless you use return command. there are two ways you can handle this
Method 1 return after showing the diaog.
#Override
protected void onResume() {
super.onResume();
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
if (connectivityManager.getActiveNetworkInfo() ==null){
noConDialog.show(getFragmentManager(), NET_ALERT_DIALOG);
Log.e("jedois","pas m'afficher");
return;
}
if (storeId == 0) { //si on a plus la boutique id
//call logon activity
Intent logonActivity = new Intent(ShoppingActivity.this, LogonStoreActivity.class);
startActivityForResult(logonActivity, LOGON_STORE_REQUEST);
}
}
Method 2 Move rest of the code into else part, so only one block could execute at a time.
#Override
protected void onResume() {
super.onResume();
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
if (connectivityManager.getActiveNetworkInfo() ==null){
noConDialog.show(getFragmentManager(), NET_ALERT_DIALOG);
Log.e("jedois","pas m'afficher");
}
else{
if (storeId == 0) { //si on a plus la boutique id
//call logon activity
Intent logonActivity = new Intent(ShoppingActivity.this, LogonStoreActivity.class);
startActivityForResult(logonActivity, LOGON_STORE_REQUEST);
}
}
}
Related
Today I have a problem in my Android project. I use a Service with a thread in it to log location information in a period of 10s. However, when I change the screen orientation (Portrait -> Landscape), the period just messed up.
I think I may run another thread so that I got one more thread running behind once I rotate the screen. I have print log messages and it seems my guessing is right.
Here is my code:
public class LocationService extends Service
{
public Location loc;
public LocationService()
{
}
#Override
public int onStartCommand(Intent intent, int flags, int id)
{
Thread thread = new Thread(new Runnable()
{
#Override
public void run()
{
LocationManager locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
if ( ContextCompat.checkSelfPermission(LocationService.this, android.Manifest.permission.ACCESS_COARSE_LOCATION ) == PackageManager.PERMISSION_GRANTED )
{
loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if(loc == null) // fall back to network if GPS is not available
{
loc = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
}
if(loc != null)
{
Timer timer = new Timer();
final String time = (new Date()).toString();
timer.scheduleAtFixedRate(new TimerTask()
{
#Override
public void run()
{
Log.d(time, "hehe");
double currentLat = loc.getLatitude();
double currentLng = loc.getLongitude();
Intent done = new Intent();
done.setAction("location");
done.putExtra("currentLat", currentLat);
done.putExtra("currentLng", currentLng);
sendBroadcast(done);
//Toast.makeText(LocationService.this, String.valueOf(currentLat) + String.valueOf(currentlng), Toast.LENGTH_LONG).show();
}
}, 10000, 10000);
}
}
else
{
Toast.makeText(LocationService.this, "Please allow app to access your location", Toast.LENGTH_LONG).show();
}
}
});
thread.start();
return START_STICKY; // stay running
}
#Override
public IBinder onBind(Intent intent)
{
// // TODO: Return the communication channel to the service.
// throw new UnsupportedOperationException("Not yet implemented");
return null;
}
// #Override
// public void onDestroy()
// {
// Log.d("hehe","onDestroy");
// super.onDestroy();
// }
}
Here is the code for activity:
public class MainActivity extends AppCompatActivity
{
private Toolbar toolbar;
private FragmentManager fragmentManager;
private LocalFragment localFragment;
private ServerFragment serverFragment;
private QueryFragment queryFragment;
private FragmentTransaction transaction;
public SQLiteHelper dbHelper;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper = new SQLiteHelper(this);
//garb handlers
fragmentManager = getFragmentManager();
localFragment = (LocalFragment) fragmentManager.findFragmentById(R.id.fragment_local);
serverFragment = (ServerFragment) fragmentManager.findFragmentById(R.id.fragment_server);
queryFragment = (QueryFragment) fragmentManager.findFragmentById(R.id.fragment_query);
// initial visibility
transaction = fragmentManager.beginTransaction();
if(this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT)
{
// toolbar (must be put in checking orientation because landscape layout does not have toolbar here)
toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setTitle(R.string.toolbar_title);
setSupportActionBar(toolbar);
transaction.show(localFragment);
transaction.hide(serverFragment);
transaction.hide(queryFragment);
transaction.commit();
}
else // ORIENTATION_LANDSCAPE
{
transaction.hide(queryFragment); // landscape orientation does not need query function (?)
transaction.show(localFragment);
transaction.show(serverFragment);
transaction.commit();
}
// register network status receiver
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
NetworkStatusReceiver myNetworkReceiver = new NetworkStatusReceiver();
registerReceiver(myNetworkReceiver, intentFilter);
// start location service
Intent intent = new Intent(this, LocationService.class);
intent.setAction("location");
startService(intent);
// register location receiver
IntentFilter intentFilterLocation = new IntentFilter();
intentFilterLocation.addAction("location");
LocationReceiver myLocationReceiver = new LocationReceiver();
registerReceiver(myLocationReceiver, intentFilterLocation);
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_main_activity, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
transaction = fragmentManager.beginTransaction();
// handle click event
if(item.getItemId() == R.id.action_online)
{
transaction.hide(localFragment);
transaction.hide(queryFragment);
transaction.show(serverFragment);
transaction.commit();
}
else if(item.getItemId() == R.id.action_offline)
{
transaction.hide(serverFragment);
transaction.hide(queryFragment);
transaction.show(localFragment);
transaction.commit();
}
else // Query
{
transaction.hide(localFragment);
transaction.hide(serverFragment);
transaction.show(queryFragment);
transaction.commit();
}
return super.onOptionsItemSelected(item);
}
// receiver for network change action
private class NetworkStatusReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) // if receive network change event broadcast
{
Toast.makeText(context, "Network status changed!", Toast.LENGTH_LONG).show();
// why I cannot use another thread to do so? CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
// Thread thread = new Thread(new Runnable()
// {
// #Override
// public void run()
// {
int type = 0;
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo(); // get current network type
if (networkInfo != null && networkInfo.isAvailable())
{
type = networkInfo.getType();
String typeName = networkInfo.getTypeName(); // (?)
//serverFragment = (ServerFragment)fragmentManager.findFragmentById(R.id.fragment_server);
if (type == ConnectivityManager.TYPE_WIFI) // wifi
{
WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
Log.d("wifiInfo", wifiInfo.toString());
Log.d("SSID",wifiInfo.getSSID());
serverFragment.setNetworkStatusText("WIFI: " + wifiInfo.getSSID()); // thread issues here. WTF
} else if (type == ConnectivityManager.TYPE_MOBILE) // Cellar
{
serverFragment.setNetworkStatusText("Mobile Data");
} else // no network
{
serverFragment.setNetworkStatusText("No Network");
}
} else // no network
{
serverFragment.setNetworkStatusText("No Network");
}
// }
// });
// thread.start();
}
}
}
// receiver for location per 10s
public class LocationReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if(action.equals("location"))
{
double currentLat = intent.getDoubleExtra("currentLat", 0.0);
double currentLng = intent.getDoubleExtra("currentLng", 0.0);
Date now = new Date();
localFragment.addNewLocation(now, currentLat, currentLng); // add to list for listview
// TODO: 11/5/16 implement SQLite insert
dbHelper.addEntry(now, currentLat, currentLng);
Toast.makeText(MainActivity.this, "Current Location: " + String.valueOf(currentLat) + ", " + String.valueOf(currentLng), Toast.LENGTH_LONG).show();
}
}
}
public void setNetworkStatus(String networkStatus)
{
serverFragment.setNetworkStatusText(networkStatus);
}
}
My Question are:
It seems that the onDestroy () method would not be called when rotate the screen?
A new Service will not be created when rotate the screen?
How can I stop the thread created previously? Or what is the best way to handle this problem?
It seems that the onDestroy() method would not be called when rotate the screen?
No, it isn't. Changing the screen orientation kills the Activity and creates a new one, but your Service is still running. Screen orientation has no effect on this.
A new Service will not be created when rotate the screen?
No. A Service is essentially a singleton. Android will not create a new instance of your Service if there is already one running. However, onStartCommand() will be called again because your Activity calls startService() when it is created.
How can I stop the thread created previously? Or what is the best way to handle this problem?
The easiest way to deal with this is to check in onStartCommand() if your thread is already running. If so, you don't need to start it again. Save a reference to your Thread in a member variable (a field) in your Service and call isAlive() on it to see if it is running.
Also, in onDestroy() you should make sure that your Thread shuts down, otherwise it will continue to run even after your Service is dead. To do that you should create a boolean member variable (field) in the Thread, which you check in each loop. In onDestroy() of your Service, set that boolean so that the Thread exits.
I have created an android apps that using async task to call web service,
when authentication fail, user will stop current activity and redirect back to login page.
My problem is when user redirect back to login page, a toast text still showing, this toast text is under async thread onPostExceute() event.
any solution for this problem?
in the webService.cs
catch (UnauthorizedException ua) {
Log.d(tag, ua.getMessage());
Intent intent = new Intent(activity, LoginActivity.class);
if(condition a){
intent.putExtra("toast_text", R.string.a);
}else{
intent.putExtra("toast_text", R.string.b);
}
activity.finish();
activity.startActivity(intent);
}
return null;
then in asyncTask.cs
protected JSONArray doInBackground(String... parameters) {
ConnectivityManager cm =
(ConnectivityManager) SingleFormActivity.this.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null &&
activeNetwork.isConnectedOrConnecting();
if (isConnected) {
}
return null;
}
public void onPostExecute(JSonArray result){
if(result != null){
}else{
Toast.makeText(Something.this, R.string.b, Toast.LENGTH_LONG).show();
}
}
you can Use
Create Toast like
Toast toast = Toast.makeText(getApplicationContext(), "", Toast.LENGTH_LONG);
and before calling finish() cancel toast using below code
if (toast != null )
toast.cancel();
Try like this
Return request status from doInBackground.and show toast using that status in onPostExecute
may be there is any syntax error in this code.But i hope it help you
public class AsyncConnectTask extends AsyncTask<Void, Void, Boolean> {
private MyInterface mListener;
public AsyncConnectTask(Context context, String address, String user,
String pass, int port, MyInterface mListener) {
}
#Override
protected Boolean doInBackground(Void... params) {
....
return result;
}
#Override
protected void onPostExecute(Boolean result) {
if (result == true) {
//Show toast here
}else{
}
}
}
In onPause() add below code
if(isFinishing()){
if (toast != null || toast.getView().getWindowVisibility() == View.VISIBLE) {
toast.cancel();
}
}
when authentication fail, user will stop current activity and redirect back to login page.
with your above question, I assume you got two different activity (one for login and another for doing something also showing the toast message. If its correct then before showing the toast check if the activity is finishing if not then show the toast.
if(!isFinishing()){
// show toast
}
http://developer.android.com/reference/android/app/Activity.html#isFinishing%28%29
I am doing offline caching.I want to allow user to make events even when he/she is offline.For that I am using a handler that checks every second whether net connection is there or not and whenever net connection is there it executes the task associated with the event.For example if user want to post comment when he/she is offline then when he click on post button a handler will run which will post the comment whenever internet connection is there on user's device.But using a handler or thread may not be the best choice as they will keep running until net connection is there and also checking condition repeatedly.Is there any other better way to allow user to schedule events when he/she is offline and execute them whenever netconnection is there?
mPostCommentImageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(isNetworkAvailable())
{
postComment(mCommentEditText.getText().toString());
hideKeypad();
mCommentEditText.setText("");
}
else
{
Toast.makeText(getActivity(),"You comment will be posted once net connection is there",Toast.LENGTH_LONG).show();
comment= new Handler();
hideKeypad();
final String commenttext=mCommentEditText.getText().toString();
comment.postDelayed(runnable = new Runnable()
{
public void run() {
addComment(videoid,commenttext,comment,runnable);
comment.postDelayed(runnable, 2000);
}
},2000);
refreshCommentList();
}
}
});
public void addComment(String videoid,String commenttext, final Handler comment,final Runnable runnable) {
if (isNetworkAvailable()) {
CommentAPI.addComments(getApplicationContext(), videoid, commenttext, new APIResponseListener() {
#Override
public void onResponse(Object response)
{
comment.removeCallbacks(runnable);
}
#Override
public void onError(VolleyError error)
{
}
});
}
}
private boolean isNetworkAvailable()
{
ConnectivityManager connectivityManager= (ConnectivityManager)getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
You can use the ConnectivityManager BroadcastReceiver for this. More information on this is available at Determining and Monitoring the Connectivity Status.
I am working on tab bar application for Android and I need to update the user about status and I want to register the whole app to a BroadcastReceiver and show Toast in all screens about the network status.
I have come up with this below code but it is only for one Activity. I am registering in onResume the same way as I did in all activities but I am getting a null pointer for currentNetworkInfo in the second tab. Any ideas how to resolve this?
this.registerReceiver(this.mConnReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
private BroadcastReceiver mConnReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
boolean noConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
String reason = intent.getStringExtra(ConnectivityManager.EXTRA_REASON);
boolean isFailover = intent.getBooleanExtra(ConnectivityManager.EXTRA_IS_FAILOVER, false);
currentNetworkInfo = (NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
if (currentNetworkInfo.isConnected()) {
Toast.makeText(getApplicationContext(), "Network connected", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(), "No Network connection", Toast.LENGTH_LONG).show();
}
}
};
I am stuck with following problem.I want my application to exit if it detects no network connection.My application starts with splash screen.Is it possible to show splash screen followed by toast if no network connection is on device.and then terminate the application
I have something like this in my splash screen code :
Inside onCreate()
ConnectivityManager connectivitymanager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkinfo = connectivitymanager.getActiveNetworkInfo();
connected = networkinfo != null && networkinfo.isAvailable()
&& networkinfo.isConnected();
Log.v("Network state : ", connected + "");
Thread splashThread = new Thread() {
#Override
public void run() {
try {
int waited = 0;
while (waited < 5000) {
sleep(100);
waited += 100;
}
} catch (InterruptedException e) {
// do nothing
} finally {
Looper.prepare();
if (connected == false) {
Toast.makeText(
splashscreenActivity.this,
"No Network Connection is available on device.",
Toast.LENGTH_LONG).show();
finish();
System.exit(0);
} else {
finish();
startActivity(new Intent(splashscreenActivity.this,
mainActivity.class));
}
Looper.loop();
}
}
};
splashThread.start();
1.Please see my code and guide me how can i show up that toast.
2.Or suggest me some other better way to do this
Thanks
EDIT :
Thank you everybody for replying :
I opted Dharmendra's way of showing toast via splashscreen activity :
The code that worked for is :
if (connected == false) {
splashscreenActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(splashscreenActivity.this,
"No Internet Connection.", 3000).show();
}
});
finish();
} else {
//migrate to main activity from splashscreen
}
You can do it like this, use Handler .Put the following code in the else condition
Handler mHandler = new Handler(Looper.getMainLooper());
mHandler.post(new Runnable() {
public void run() {
Toast.makeText(Splash.this, "Network error", Toast.LENGTH_LONG).show();
finish();
}
});
Or ,I am doing this in my application :
if(status.equals("CONNECTED"))
{
startActivity(new Intent(Splash.this,Activity.class));
finish();
}else
{
startActivity(new Intent(Splash.this,NetworkError.class));
finish();
}
where NetworkError class shows another layout with the image like "No Network,,,,"(or whatever you want to show instead of splash...)
You are creating and showing Toast from Thread so it may be not called
You have to write this code
splashscreenActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(c, "Internet connection not currently available.", 3000).show();
}
});
Just add a if else block.(using ur connection network info)
if(connected){
//put the splash thread here
}else{
finish();
}
A finally block is used if you do not wish to catch any exceptions. In your code, place all your code in a else loop, If time of 5000 lapses then, go to else statement and execute it. If you are adding catch you can remove finally.