Handling offline events - android

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.

Related

How to set a fixed time if AsyncTask is not finished

I have an asynctask and I'm looking to do a wait if the async is taking too long, I'm downloading some data of the database , but I don't want to have the user looping around the progressdialog, I want to set a fixed time, lets say I'm downloading a file but is taking forever, so I tell the user, "hey, check your internet connection and try again" I'm looking to do this with a timer, but I'm kinda stuck, this is where I do my asynctask
private class DownloadFilesTask extends AsyncTask<Void, Void, Void> {
String s;
public DownloadFilesTask(String s){
this.s = s;
}
#Override
protected Void doInBackground(Void... voids) {
DownloadMethod(s);
return null;
}
}
so let's say I want to execute that downloadmethod for a fixed time, 10 or 20 seconds, if the file is not downloaded at that time I return a message to the user saying that he needs to check for hes internet.
You can use handler to run after a definite amount time and maintain a boolean flag which you can update in postExecute function of async task.
In your activity/fragment class:
new Handler().postDelayed(new Runnable(){
public void run(){
//Check whether the flag has been updated or not
},1000)
You can use BroadcastReceiver to listen your internet connection. Here is an example:
public class NetworkControl extends BroadcastReceiver {
static boolean isConnected = false;
#Override
public void onReceive(final Context context, final Intent intent) {
isNetworkAvailable(context);
}
private boolean isNetworkAvailable(Context context) {
ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity != null) {
NetworkInfo[] info = connectivity.getAllNetworkInfo();
if (info != null) {
for (int i = 0; i < info.length; i++) {
if (info[i].getState() == NetworkInfo.State.CONNECTED) {
if(!isConnected){
isConnected = true;
Toast.makeText(context, "You're online!!", Toast.LENGTH_LONG).show();
}
return true;
}
}
}
}
isConnected = false;
Toast.makeText(context, "Connection interrupted.", Toast.LENGTH_LONG).show();
return false;
}
}
Also you need some permissions in AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
Then start the service in your activity.
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
receiver = new NetworkControl();
registerReceiver(receiver, filter);
If you are using HttpURLConnection to download the file then you can do something like this:
private class DownloadFilesTask extends AsyncTask<String, Integer, Integer> {
#Override
protected Integer doInBackground(String... ulr) {
URL url = null;
try {
url = new URL(ulr[0]);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setConnectTimeout(2000); //Timeout
//...Other codes for downloading
return 101;
} catch (java.net.SocketTimeoutException e) {
return 102;
} catch (MalformedURLException e) {
return 103;
} catch (IOException e) {
return 104;
}
}
#Override
protected void onPostExecute(Integer result) {
if(result == 102) {
Toast.makeText(getApplicationContext(), "Connection Timeout.", Toast.LENGTH_LONG).show();
}
}
}
First thing I want to say that is, while running downloading task it's not a good practice, to message a user that check your internet connection or
no internet connection. Because in this condition, if user do switch off then on network connection then your downloading task restarts again and takes whole time again. So, avoid this types of messages.
Now about solution, after execute background task you can check your task is running or completed. If it takes too much time
then show a message. For example,
YourBackgroundTask task = new YourBackgroundTask();
task.execute();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
if (task.getStatus == AsyncTask.Status.RUNNING){
Toast.makeText(this, "Please wait...", Toast.LENGTH_SHORT).show();
}
}
},20000); // time in milisecond
And if you want to repeat this, you can easily re-run handler.
Here is a basic idea you can try if it works
private class DownloadFilesTask extends AsyncTask<Void, Integer, Void> implements TimerTask{
String s;
Timer timer;
Object objectResult;
public DownloadFilesTask(String s){
this.s = s;
timer = new Timer();
}
#Override
protected Void doInBackground(Void... voids) {
objectResult = DownloadMethod();
return null;
}
private Object DownloadMethod() {
//here implement the download logic and return the object
return null;
}
#Override
protected void onProgressUpdate(Integer... progress) {
// your code to update progress
}
public void checkProgress(){
timer.schedule(this,2000);
}
#Override
public void run() {
if (objectResult!=null){
//download completed
}else{
//show dialog here and schedule a task again
timer.schedule(this,2000);
}
}
}

activity.finish() is not stopped current activity

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

Android internet connection checking [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Android - detect whether there is an Internet connection available
this is the code to check the internet availability on android device:
public boolean isInternetAvailable() {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
if (cm.getActiveNetworkInfo() != null)
return cm.getActiveNetworkInfo().isConnected();
else
return false;
}
So this code is working correctly if no wifi or network available.
But if device is connected to wifi network but internet is not available then what should i do to check the internet is there or not?
any suggestion will be appreciated.
I do it like this:
I try to reach google.com and watch for response:
public static void isGoogleAvailable(final Handler handler)
{
new Thread()
{
private boolean hasGoogleResponded = false;
#Override
public void run()
{
new Thread()
{
#Override
public void run()
{
HttpGet requestForTest = new HttpGet("https://www.google.com/");
try
{
new DefaultHttpClient().execute(requestForTest);
hasGoogleResponded = true;
}
catch (Exception e)
{}
}
}.start();
try
{
int waited = 0;
while(!hasGoogleResponded && (waited < 60000))
{
sleep(100);
if(!hasGoogleResponded )
{
waited += 100;
}
}
}
catch(InterruptedException e)
{}
finally
{
if (hasGoogleResponded)
{
handler.sendEmptyMessage(1);
}
else
{
handler.sendEmptyMessage(0);
}
}
}
}.start();
}
Then I retrive messages in my handler:
Handler internetHandler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
if (msg.what == 1) //connected
{
}
else //not connected
{
}
}
};
I hope this helps.
You could try to ping a server like google (that should always exist)
see this topic
You can try
ConnectivityManager m;
m.getAllNetworkInfo();
First check internet connection,then others.
But sometimes its depends on app architecture.
If application needed wifi and you havent - you can not check internet because
it is not necessary

Android update UI from Thread (Handler maybe not an option?)

This is a common question, and I have read up on the various ways of handling it, but each on seems to fall short for what I am trying to do, which is essentially be a good OO-Citizen.
I have an Activity that invokes a CommunicationManager, which basically polls a TCP socket for data. When the CommunicationManager receives data, it throws a custom event (containing the string it just fetched), which is handled by the Activity. I am doing this, A) because other classes will depend on that data, not just the Activity, and B) because the polling is asynchronous, and should fire an event when it receives results.
My problem lies in that I need to surface those results into a TextView on the UI. I have the polling mechanism all set up, it fires every 1000ms, and invokes the event handler on the Activity. However, the UI never updates.
Assumedly this is a thread issue and the UI thread is not the one getting the change to the TextView, but how do I do this?? I have tried using a Handler, but am not sure where to put it, and when I did get it compiling it never updated the UI.
This seems relatively trivial if everything was done within the Activity, but adding in this other class (CommunicationManager) and the event is making it very confusing for me.
Here is what I have so far:
ACTIVITY (polling is invoked by clicking a button on the UI):
public void onClick(View v) {
if (v.getId() == R.id.testUDPBtn) {
statusText.setText("");
commMgr = new CommunicationManager();
commMgr.addEventListener(this);
MediaPositionPollThread poller = new MediaPositionPollThread(commMgr);
poller.startPolling();
}
}
#Override
public void handleMediaPositionFoundEvent(MediaPositionFoundEvent e) {
statusText.append(e.userData);
}
THREAD:
class MediaPositionPollThread extends Thread {
private CommunicationManager commManager;
private static final String TAG = "MediaPositionPollThread";
private boolean isPolling = false;
public MediaPositionPollThread(CommunicationManager cm) {
commManager = cm;
}
public void startPolling() {
isPolling = true;
this.run();
}
public void stopPolling() {
isPolling = false;
}
#Override
public void run() {
while (isPolling) {
try {
commManager.getCurrentMediaPosition();
Thread.sleep(1000);
}
catch (InterruptedException e) {
Log.d(TAG, "EXCEPTION: " + e.getMessage());
}
}
}
}
COMMUNUCATION MANAGER:
public void getCurrentMediaPosition() {
PrintWriter outStream;
BufferedReader inStream;
String resultString = "";
try {
outStream = new PrintWriter(tcpSocket.getOutputStream(), true);
outStream.println("GET?current_pts");
inStream = new BufferedReader(new InputStreamReader(tcpSocket.getInputStream()));
resultString = inStream.readLine();
fireEventWithData(resultString);
} catch (Exception e) {
e.printStackTrace();
}
}
public synchronized void addEventListener(MediaPositionFoundEventListener listener) {
_listeners.add(listener);
}
public synchronized void removeEventListener(MediaPositionFoundEventListener listener) {
_listeners.remove(listener);
}
private synchronized void fireEventWithData(String outputString) {
MediaPositionFoundEvent evt = new MediaPositionFoundEvent(this);
evt.userData = outputString;
Iterator<MediaPositionFoundEventListener> i = _listeners.iterator();
while(i.hasNext()) {
((MediaPositionFoundEventListener) i.next()).handleMediaPositionFoundEvent(evt);
}
}
So I have the Activity making a thread that gets executed every second, calling CommunicationManager >> getCurrentMediaPosition, which in turn fires the MediaPositionFoundEvent, which is handled by the Activity and updates the TextView (statusText) on the screen.
Everything works except the screen not updating. I have tried runOnUiThread, and a Handler, but am obviously not getting it right.
Thanks in advance for any insight or solutions!
In your Activity class, add a private Handler _handler,
Initialize it in your onCreate Activity method,
and change your handleMediaPositionFoundEvent method to
#Override public void handleMediaPositionFoundEvent(MediaPositionFoundEvent e) {
_handler.post(new Runnable(){
public void run(){
statusText.append(e.userData);
});
}
}
It looks like your blocking the UI thread with your custom Thread. Please update this method to call start() vs run().
public void startPolling() {
isPolling = true;
this.start();
}

Show Toast on SplashScreen Android

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.

Categories

Resources