I would like to display "Connecting ..." using Toast until the device is connected to a new network (more specifically when an IP address is obtained, see the while loop in doInBackground below). I am using AsyncTask for connecting to the network, but if I put Toast.makeText(...).show() inside onProgressUpdate() the toast calls will stack and end up displaying the text way longer than desired. My Connect class:
public class Connect extends AsyncTask<Object,Void,Void>{
private static final String TAG="sure2015test";
private Context context;
private Network network;
#Override
protected Void doInBackground(Object... params) {
this.network=(Network)params[0];
this.context=(Context) params[1];
final WifiConfiguration conf = new WifiConfiguration();
conf.SSID = "\"" + network.ssid + "\"";
if(network.password!=null){
conf.preSharedKey = "\""+ network.password +"\"";
}
else{
conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
}
if(network.manager.addNetwork(conf)==-1){
Log.i(TAG, "Add network fail");
}
List<WifiConfiguration> configs = network.manager.getConfiguredNetworks();
for (WifiConfiguration i : configs) {
if (i.SSID != null && i.SSID.equals("\"" + network.ssid + "\"")) {
network.manager.disconnect();
if(network.manager.enableNetwork(i.networkId, true)==false){
Log.i(TAG,"Enable Network fail ");
}
if(network.manager.reconnect()==false) {
Log.i(TAG, "Reconnect fail");
}
}
}
WifiInfo info=network.manager.getConnectionInfo();
while((info.getIpAddress())==0){
//Wait until non-zero IP address (once a non-zero ip address is obtained, you are connected to the network)
//Tried to use NetworkInfo.DetailedState to check if it was CONNECTED
//However the api method said it remained in OBTAINING_IPADDR state even after it obtained an ip (must be bug)
info=network.manager.getConnectionInfo();
publishProgress();
Log.i(TAG,"IP "+info.getIpAddress());
try{
Thread.sleep(100);
}
catch(InterruptedException e){
Log.i(TAG,"Interrupted exception");
}
}
return null;
}
#Override
protected void onProgressUpdate(Void... values) {
Toast.makeText(context, "Connecting ...", Toast.LENGTH_SHORT).show();
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(Void aVoid) {
Toast.makeText(context,"Connected",Toast.LENGTH_SHORT).show();
Intent newActivity = new Intent(context, Device.class);
newActivity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
newActivity.putExtra("Device", network.ssid);
context.startActivity(newActivity);
super.onPostExecute(aVoid);
}
}
I'd suggest using a ProgressDialog instead of a Toast. You can show it before running the AsyncTask and hide it onPostExecute. It'd look something like.-
ProgressDialog dialog = ProgressDialog.show(CurrentActivity.this, "", "Connecting...", true, false);
[...]
dialog.dismiss();
By the way, don't forget to put your string literals in a Strings resources file :)
Toast is not a good practise to show progress work. Toast is designed to show minor and fast information(ex. In your case is to show that devise is connected), but in my opinion it's better to implement ProgressBar in your layout and set it visible while AsyncTask execute doInBackground and set it invisible in onPostExecute.
If you need to show Toast within the other thread, also within doInBackground(Object... params), you can use:
YourActivity.this.runOnUiThread(new Runnable() {
public void run() {
//put here your thread
}
});
Hovewer, you need to get Context in this case. I make it with static variable. But do not forget, the Toast is appearing only for short time and you can't manage it. If you need to show the message all the time you do some stuff, you can use ProgressDialog
Related
I am trying to disable a button while a download task is being executed. I have tried using setEnabled, setVisibility and setClickable. I think I tried all combinations of these options. All of them disable the button click events while the task is performing, but the events are still being registered somehow, and when I reactive the button, the handler is called if I clicked the button while it was disabled... even if it was invisible or "gone"! (not sure if it is called a handler, I want to refer to the onClick method).
I have also inserted a counter and a Log to verify what I've stated above. The code is shown below. This piece of code if(counter>1) return; is meant to stop the crash, but I would like to remove it, since I want to re-enable the button, and not disable it forever.
onClick:
public void downloadOnClick(View v) {
counter++;
Log.d(this.getLocalClassName(), "Button was clicked " + counter + " times.");
if(counter>1) return;
ConnectivityManager connMgr = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
//mButton.setVisibility(View.GONE);
mButton.setEnabled(false);
//mButton.setClickable(false);
mTextView.setText("Getting html file...");
// if we use simple http, we will need to handle redirect status code
new DownloadWebpageTask().execute("https://www.google.com/");
} else {
mTextView.setText("No network connection available.");
}
}
AsyncTask:
private class DownloadWebpageTask extends AsyncTask<String, Void, String> {
private HttpURLConnection mConnection;
#Override
protected String doInBackground(String... urls) {
try {
URL url = new URL(urls[0]);
mConnection = (HttpURLConnection) url.openConnection();
mConnection.setReadTimeout(10000 /* milliseconds */);
mConnection.setConnectTimeout(15000 /* milliseconds */);
mConnection.setRequestMethod("GET");
mConnection.setDoInput(true);
mConnection.connect();
int statusCode = mConnection.getResponseCode();
if (statusCode != HttpURLConnection.HTTP_OK) {
return "Error: Failed getting update notes";
}
return readTextFromServer(mConnection);
} catch (IOException e) {
return "Error: " + e.getMessage();
}
}
private String readTextFromServer(HttpURLConnection connection) throws IOException {
InputStreamReader stream = null;
try {
stream = new InputStreamReader(connection.getInputStream());
BufferedReader br = new BufferedReader(stream);
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null) {
sb.append(line + "\n");
line = br.readLine();
}
return sb.toString();
} finally {
if (stream != null) {
stream.close();
}
}
}
#Override
protected void onPostExecute(String result) {
mTextView.setText(result);
// Can not reactivate button / cancel (pending?) events....
//mButton.setVisibility(View.VISIBLE);
mButton.setEnabled(true);
//mButton.setClickable(true);
}
}
The full project (it is very simple, just a training example) is available to test in this repository that I have just created.
To conclude, from what I have read, there is in fact a problem regarding button disabling. Mostly this is resolved through the use of a flag to call the onClick method only when the flag is true. Although, this does not solve the problem of re-enabling the button. I have also tried mButton.cancelPendingInputEvents(); but it does not work (and I do not know why. Click events are not yet registered? Or they are not pending?
Is there a simple solution to this problem? Any ideas? Am I missing some basic detail? If not, I am considering trying to create a new button programatically to contour the problem. If I do not keep references to old buttons, are they deleted through garbage collection?
Thanks in advance!
[Edit] Clarification:
Since the title could be misleading in this point, I want to clarify that I am able to disable and re-enable the button and all the functionality is ok except when the buttion is disabled. And note that I have added the line if(counter>1) return; just to test but it stops the button from working the way I wanted (that's why I am not using a flag. I don't want this line to be there when I solve the problem!). The log is enough to inform me that the method is being called when the button is re-enabled, because I clicked it when it was disabled!
I found that with your example, the AsyncTask was completing so fast that there was a very short amount of time that the Button was not clickable due to being disabled. So, it's basically a timing issue.
I found that by delaying the re-enabling of the Button by 4 seconds, it works as expected.
Note with this change that visually, the Button is re-enabled a split second after the TextView is populated.
Here is the code change in onPostExecute():
#Override
protected void onPostExecute(String result) {
mTextView.setText(result);
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
//re-enable the button
mButton.setEnabled(true);
}
}, 4000);
}
Note that you can remove the counter logic and it should work as expected now:
public void downloadOnClick(View v) {
Log.d(this.getLocalClassName(), "Button was clicked");
ConnectivityManager connMgr = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
mButton.setEnabled(false);
mTextView.setText("Getting html file...");
// if we use simple http, we will need to handle redirect status code
new DownloadWebpageTask().execute("https://www.google.com/");
} else {
mTextView.setText("No network connection available.");
}
}
The error is here:
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="DOWNLOAD TEXT"
android:id="#+id/button"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:onClick="downloadOnClick" />
You are missing the concept of OnClickListener! First of all, you have to modify the above xml in this way removing onClick attribute:
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="DOWNLOAD TEXT"
android:id="#+id/button"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
Than you have to modify the Activity onCreate method in order to set the OnClickListener on your button:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView) findViewById(R.id.text);
mButton = (Button) findViewById(R.id.button);
mButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
counter++;
Log.d(this.getLocalClassName(), "Button was clicked " + counter + " times.");
if(counter>1) return;
ConnectivityManager connMgr = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
mButton.setEnabled(false);
mTextView.setText("Getting html file...");
// if we use simple http, we will need to handle redirect status code
new DownloadWebpageTask().execute("https://www.google.com/");
} else {
mTextView.setText("No network connection available.");
}
}
});
}
This is the right way to handle a click.
See more:
Button | Android Developer
Moreover:
The best way from my point of view is implements the OnClickListener() on your Activity:
public class MyActivity extends Activity implements View.OnClickListener {
}
In this way you can write for each button where you need to set the OnClickListener do:
buttonX.setOnClickListener(this);
buttonY.setOnClickListener(this);
buttonZ.setOnClickListener(this);
In your Activity onClick() you must override the OnClickListener methods, so:
#Override
public void onClick(View v) {
if(v.getId() == R.id.ButtonX)){
//do here what u wanna do.
} else if(v.getId() == R.id.ButtonY){
//do here what u wanna do.
} else if(v.getId() == R.id.ButtonZ){
//do here what u wanna do.
}
}
Also in onClick you could use view.getId() to get the resource ID and then use that in a switch/case block to identify each button and perform the relevant action.
I'm working on a relatively simple login app for a school project. I'm having an issue connecting my app to any URL, local or otherwise. I've added the permission for internet access to the android manifest file.
<uses-permission android:name="android.permission.INTERNET" />
The following code is located in my main activity:
public class MainActivity extends Activity {
private EditText username=null;
private EditText password=null;
private Button login;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
username = (EditText)findViewById(R.id.ucidText);
password = (EditText)findViewById(R.id.passText);
login = (Button)findViewById(R.id.button1);
//URL CAN BE ANYTHING, WOULD NORMALLY BE 192.168.1.102
if(isConnectedToServer("<-URL to page on locally hosted server->",10)){
Toast.makeText(getApplicationContext(), "Connected", Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(getApplicationContext(), "Connection failed", Toast.LENGTH_SHORT).show();
}
}
//Function to determine if connection exists
public boolean isConnectedToServer(String url, int timeout) {
try{
URL myUrl = new URL(url); //<--------- I believe the issue has to do with this line.
URLConnection connection = myUrl.openConnection();
connection.setConnectTimeout(timeout);
connection.connect();
return true;
} catch (Exception e) {
return false;
}
}
}
This is a stripped down version of my overall project. Everything checks out except the connectivity. I'm running the app from the SDK straight on my phone (Moto X). Any suggestions?
You got the android.os.NetworkOnMainThreadException because you perform your network request on the main thread. You should not do that because you will block the main thread. Instead, you can start a new thread to perform your network request, like this:
final Handler handler = new Handler();
new Thread(){
public void run(){
// check network connection here.
handler.post(/* do the toast work in a Runnable as the parameter here*/);
}
}.start();
You should use some protocol in the "url" string.
For example, you can use
"http://serverIP"
in which the serverIP is 192.168.1.102 and the port is default to 80.
We could not use "192.168.1.102" as the url because the protocol could not be ignored for the URL class.
Ever get those moments where you stare at a piece of code for an hour and still can't come up with an answer? Yeah that's me now.
I'm working on a final project for class and I can't get this one piece of code to work. It is absolutely crucial that it works, or else it defeats the purpose of the program. I even asked my professor for help... and he doesn't know how to help me solve the issue. I posted a similar problem a day ago but I want to re-ask in a different way to see if it helps (Sorry if its a re-post, I have no other source for help :/).
My problem is that I need to access array elements on my MainActivity after its populated inside an AsyncTask class. The array is defined globally but as soon as I try to access it's element or size, it crashes. I need to be able to call this array outside of AsyncTask.
I've searched for hours and tried "returning" the array from AsyncTask but it crashes as well.
Here is my code (I've included comments as to where it crashes):
public class PostsActivity extends Activity {
public static GlobalRates[] gr;
TextView view;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_posts);
view = (TextView) findViewById(R.id.textView1);
BitRateFetcher br = new BitRateFetcher();
br.execute();
// !!! Line below crashes !!!
Log.i("BitRateFetcher", "Size from onCreate: " + gr.length);
}
private class BitRateFetcher extends AsyncTask<Void, Void, GlobalRates[]> {
private static final String TAG = "BitRateFetcher";
public String BIT_PAY_SERVER = "https://bitpay.com/api/rates";
private ProgressDialog dialog;
GlobalRates[] test;
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new ProgressDialog(PostsActivity.this);
dialog.setMessage("Please Wait... Downloading Information");
dialog.show();
}
#Override
protected GlobalRates[] doInBackground(Void... params) {
try {
// Create an HTTP client
HttpClient client = new DefaultHttpClient();
HttpGet getBitRates = new HttpGet(BIT_PAY_SERVER);
// Perform the request and check the status code
HttpResponse bitRatesResponse = client.execute(getBitRates);
StatusLine bitRatesStatus = bitRatesResponse.getStatusLine();
if (bitRatesStatus.getStatusCode() == 200) {
HttpEntity entity = bitRatesResponse.getEntity();
InputStream content = entity.getContent();
try {
// Read the server response and attempt to parse it as
// JSON
Reader reader = new InputStreamReader(content);
Gson gson = new Gson();
test = gson.fromJson(reader, GlobalRates[].class);
content.close();
entity.consumeContent();
} catch (Exception ex) {
Log.e(TAG, "Failed to parse JSON due to: " + ex);
failedLoadingPosts();
}
} else {
Log.e(TAG, "Server responded with status code: "
+ bitRatesStatus.getStatusCode());
failedLoadingPosts();
}
} catch (Exception ex) {
Log.e(TAG, "Failed to send HTTP POST request due to: " + ex);
failedLoadingPosts();
}
return test;
}
#Override
protected void onPostExecute(GlobalRates[] test) {
Log.i(TAG, "Test Size: " + test.length); // Returns 158
gr = test;
Log.i(TAG, "Gr Size: " + gr.length); // Returns 158
if (dialog.isShowing()) {
dialog.dismiss();
}
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.posts, menu);
return true;
}
private void failedLoadingPosts() {
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(PostsActivity.this,
"Failed to load Posts. Have a look at LogCat.",
Toast.LENGTH_SHORT).show();
}
});
}
}
Here is the error Log:
04-21 20:30:01.954: E/AndroidRuntime(32595): FATAL EXCEPTION: main
04-21 20:30:01.954: E/AndroidRuntime(32595): Process: com.example.postsactivity, PID: 32595
04-21 20:30:01.954: E/AndroidRuntime(32595): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.postsactivity/com.example.postsactivity.PostsActivity}: java.lang.NullPointerException
My class partner and I are unsure as to how we can call the global array (gr) properly. I understand that onCreate is not going to wait for AsyncTask to finish. What can we do to get this to work? Thanks for the help and understanding. You guys can prove more useful than my professor...
the problem is that you are accessing array of globalrates before it was initialized in your postExecute(). There are a lot of way to do this one of which is creating an interface or creating callbacks that waits for globalrate to be initialized after ur background thread is done.
Create a Interface
public interface SampleInterface {
void globalResultBackground(GlobalRates[] gr);
}
implements the interface to ur activity
public class PostsActivity extends Activity implements SampleInterface
pass the interface to your asynctask
//in the activity
BitRateFetcher br = new BitRateFetcher(this);
br.execute();
//in the asynctask class
SampleInterface si;
public BitRateFetcher(SampleInterface si){
this.si = si;
}
pass the result of the background thread to ur interface method
#Override
protected void onPostExecute(GlobalRates[] test) {
si.globalResultBackground(test);
Log.i(TAG, "Test Size: " + test.length); // Returns 158
gr = test;
Log.i(TAG, "Gr Size: " + gr.length); // Returns 158
if (dialog.isShowing()) {
dialog.dismiss();
}
}
in the activity where the you implemented the interface and generated the globalResultBackground method
#Override
public void globalResultBackground(GlobalRates[] gr) {
//you can freely access the globalrates here because this is called when the
//background thread is done
Log.i("BitRateFetcher", "Size from onCreate: " + gr.length);
}
Pass in your activity to the AsyncTask and directly access its gr in your onPostExecute
Sample code:
private class BitRateFetcher extends AsyncTask {
PostsActivity activity;
...
public BitRateFetcher(PostsActivity activity){
this.activity= activity;
}
...
#Override
protected void onPostExecute(GlobalRates[] test) {
activity.gr = ...
}
}
In PostsActivity,
BitRateFetcher br = new BitRateFetcher(this);
Take care to attach and reAttach the activity to handle scenarios such as device rotations.
EDIT: Just noticed you've got a static, so you don't even need to pass in the activity. The same principle applies though.
GlobalRates[] gr is public and static, so you dont really new GlobalRates[] test
simply replace every instance of test with gr:
test = gson.fromJson(reader, GlobalRates[].class);
to
gr = gson.fromJson(reader, GlobalRates[].class);
if you need to access gr in Oncreate then move that logic to postExecute
Log.i("BitRateFetcher", "Size from onCreate: " + gr.length);
Suppose phone finds open wi-fi network and connects to it. But wi-fi network is "inactive", i.e. when you open browser you see prompt for credentials. I have many apps on my phone(for example web-browser), which fail to work in such cases.
I want to send data using mobile network, but system still tries to use wi-fi.
NetworkInfo.isAvailable() and NetworkInfo.isConnected() still return true for the described wi-fi networks.
Any solution?
I've been having the same problem, and what I found is there is no such possibility via the Android SDK, you have to write your own way to do it.
It depends what do you want to do with the network and what do you mean by 'inactive' - you can be connected to a router, which doesn't have connection to the Internet, and there is no Android method to check such situation. As MrMichael wrote, ping is one way to check it, but in that case positive test gives you just info about ping - the network can have some heavy firewall which allows you to send pings, but i. e. will not let HTTP request through.
In that case, you have to write your own custom test for your own needs, alas - that's what I did. I just implemented simple ping-like protocol (I try to connect my socket on proper IP/port and send short message waiting for short answer). Only that gives me 100% warranty that the connection I want can be established.
As far as I am aware there is no way to force the use of a data connection over wifi (perhaps something that you shouldn't do without user interaction anyway).
I have the same requirements in many of my applications, I want to know if they have a viable network connection whilst the splash screen is loading (for example I show a read only version of the app if not).
The way that I get around this is to fire a simple service call to my server called isAlive which just returns a true imedialtly. This not only tells me that I am able to see my service, it also confirms that my server is on-line (no issues at my end). In the case that I do not get a response back in a timely fashion I inform the user that they have no network connection and "Please ensure you have a valid data/wifi connection before continuing". I then take the isConnected property for the wifi and modify this message to say "Your current Wireless connection does not internet access" or something similar.
Not quite the answer you were hoping for but maybe a possibility?
Just a suggestion: You may try using requestRouteToHost(). But first search SO for problems in using this method.
Also you'll need the CHANGE_NETWORK_STATE permission.
Try this....
I needed to do some custom work..but got it up and running...
My code switches from Wifi to Mobile network when its off.
And I am using the TimeService at port 37 to know that the Internet is DEAD while the wifi connection is still ON
//////////////////////////Edited//////////////////////////////////
Now i am putting here a complete working code i made. Please pardon me as the DRY (Don't Repeat Yourself Principle ) has been abused here. So please refactor the code and convert the duplicate codes into method , ie into a single sensible place, when using in production network
/////---------------------------Intial Available Network Checking
private boolean checkConnection(){
boolean connected = false;
ConnectivityManager cm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
if (cm != null) {
NetworkInfo[] netInfo = cm.getAllNetworkInfo();
for (NetworkInfo ni : netInfo) {
if ((ni.getTypeName().equalsIgnoreCase("WIFI")
|| ni.getTypeName().equalsIgnoreCase("MOBILE"))
& ni.isConnected() & ni.isAvailable()) {
connected = true;
}
}
}
return connected;
}
/////---------------------------Intial Available Network Checking
/////-------------------------------Check for the working Internet Connection
public boolean inetAddr(){
boolean x1 = false;
try {
Socket s = new Socket("utcnist.colorado.edu", 37);
InputStream i = s.getInputStream();
Scanner scan = new Scanner(i);
while(scan.hasNextLine()){
System.out.println(scan.nextLine());
x1 = true;
}
} catch (Exception e) {
x1 = false;
}
return x1;
}
/////-------------------------------Check for the working Internet Connection
////-------------------------------Check Mobile Conectivity Again
public boolean mobileConnect(){
boolean conn = false;
ConnectivityManager cm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNet = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
if(activeNet != null){
conn = true;
}else{
conn = false;
}
return conn;
}
////------------------------------Check Mobile Conectivity Again
Here i am using the Above Methods....
try{
if (!checkConnection()){
AlertDialog.Builder myAlertDialog = new AlertDialog.Builder(YumZingSplashActivity.this);
myAlertDialog.setTitle("--- Connectivity Check ---");
myAlertDialog.setMessage("No Internet Connectivity");
myAlertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
YumZingSplashActivity.this.finish();
//splashHandler.removeCallbacks(launcherRunnable);
}});
System.out.println("No Internet Connectivity");
myAlertDialog.show();
}
else{
if(inetAddr()){
aphandle = APIHandling.getInstance();
aphandle.xmlCreateSession();
System.out.println("Net Connectivity is Present");
DURATION = Integer.valueOf(getString(R.string.splash_duration));
splashHandler = new Handler();
// ================ Main Code of the Application
launcherRunnable = new Runnable() {
public void run() {
Intent i = new Intent(YumZingSplashActivity.this, YumZingTabHostActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
YumZingSplashActivity.this.finish();
}
};
if (DEBUG)
{
splashHandler.post(launcherRunnable);
}
else{
splashHandler.postDelayed(launcherRunnable, DURATION);
}
}
else{
if(mobileConnect()){
if(inetAddr()){
aphandle = APIHandling.getInstance();
aphandle.xmlCreateSession();
System.out.println("Net Connectivity is Present");
DURATION = Integer.valueOf(getString(R.string.splash_duration));
splashHandler = new Handler();
// ================ Main Code of the Application
launcherRunnable = new Runnable() {
public void run() {
Intent i = new Intent(YumZingSplashActivity.this, YumZingTabHostActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
YumZingSplashActivity.this.finish();
}
};
if (DEBUG)
{
splashHandler.post(launcherRunnable);
}
else{
splashHandler.postDelayed(launcherRunnable, DURATION);
}
}else{
AlertDialog.Builder myAlertDialog = new AlertDialog.Builder(YumZingSplashActivity.this);
myAlertDialog.setTitle("--- Connectivity Check ---");
myAlertDialog.setMessage("No Internet Connectivity");
myAlertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
YumZingSplashActivity.this.finish();
//splashHandler.removeCallbacks(launcherRunnable);
}});
System.out.println("No Internet Connectivity");
myAlertDialog.show();
}
}else{
AlertDialog.Builder myAlertDialog = new AlertDialog.Builder(YumZingSplashActivity.this);
myAlertDialog.setTitle("--- Connectivity Check ---");
myAlertDialog.setMessage("No Internet Connectivity");
myAlertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
YumZingSplashActivity.this.finish();
//splashHandler.removeCallbacks(launcherRunnable);
}});
System.out.println("No Internet Connectivity");
myAlertDialog.show();
}
}
}
//setContentView(R.layout.yumzing_splash_layout);
} catch(Exception ex){
System.out.println("Leak ko catch");
}
}
You could connect to the wifi network, try connect to any page in background and verify if there is any redirection. If so, it is very likely to be the credential pages. In fact when I was trying to find how to implement the solution I have just described, I found it to be described in HttpURLConnection class documentation at Android developers site. There you can read:
Handling Network Sign-On
Some Wi-Fi networks block Internet access until the user clicks through a sign-on page. Such sign-on pages are typically presented by using HTTP redirects. You can use getURL() to test if your connection has been unexpectedly redirected. This check is not valid until after the response headers have been received, which you can trigger by calling getHeaderFields() or getInputStream(). For example, to check that a response was not redirected to an unexpected host:
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
if (!url.getHost().equals(urlConnection.getURL().getHost())) {
// we were redirected! Kick the user out to the browser to sign on?
...
} finally {
urlConnection.disconnect();
}
}
Try
InetAddress.getByName(host).isReachable(timeOut)
I have an application which needs to communicate with the server at some random interval through GPRS or EDGE.. But there are few possibilities at which internet cannot be accessed by the application when the user is in call or deactivated etc. At these time i have two scenario's recoverable and non recoverable.
Recoverable scenarios
On phone call ( User will hang up and data connection will be active
again)
No Signal (Sometimes signal may drop and the phone will get
signal again)
Non Recoverable Scenarios
Flight mode
Deactivating Data Connection
When its recoverable i can try again for the connection after some defined interval. And during non recoverable i have to alert user. For instance if the user deactivates data connection or enables flight mode i have to alert the user.
EDIT:I can able to detect flight mode through one of the intents. I couldn't able to find for others.
The below code return if valid connections are available
public boolean isConnectionsAvailable() {
boolean lRet = false;
try{
ConnectivityManager conMgr = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info= conMgr.getActiveNetworkInfo();
if(info != null && info.isConnected()) {
lRet = true ;
}else{
lRet = false ;
}
}catch (Exception e) {
Log.d("Connection Error", e.toString());
lRet = false ;
}
return lRet;
}
After this, if you have low signal strength then you make a HTTP request by setting relevant time out to it. If timeout happened give relevant alert msg to user as below
public void serverCall(String pURL){
if (isConnectionsAvailable()){
// Call server by setting proper timeout
}
}
Edit:
To check the Airplane mode status:
private static boolean isAirplaneModeOn(Context context) {
return Settings.System.getInt(context.getContentResolver(),
Settings.System.AIRPLANE_MODE_ON, 0) != 0;
}
You could try surrounding your method with try and catch. If the method fails because it cannot connect to your server for whatever reason you could call postDelayed from a Handler and re-run your method again in a pre-determined length of time.
Handler mHandler = new Handler();
Runnable yourMethodRunnable = new Runnable(){
#Override
public void run(){
yourMethod();
}
};
private void yourMethod(){
try{
// talk to server
} catch (InCallException e) {
mHandler.postDelayed(yourMethodRunnable, delay)
} catch (NoSignalException e) {
// etc...
} catch (OtherException e) {
// etc...
}
}
The exceptions are just examples, and likely don't exist, get the exceptions that you want to catch either from the Android Developer Docs, or by looking at the output from LogCat when you re-enact each time that the connection to the server would fail.