I have a specific question about wifi connection in Android.I'm working on a project which is downloading some data from web server and every time before starting the synchronization I'm checking about internet connection like this :
public static boolean isOnline(Context context) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
if (netInfo != null && netInfo.isConnectedOrConnecting()) {
return true;
}
return false;
}
public static boolean chkNetworkStatus(Context context) {
boolean result = false;
new Thread() {
#Override
public void run() {
for(int i=0;i<3;i++){
HttpGet requestForTest = new HttpGet("http://m.google.com");
try {
new DefaultHttpClient().execute(requestForTest);
responded = true;
} catch (Exception e) {
responded = false;
}
}
}
}.start();
boolean isOnline = isOnline(context);
if(responded && isOnline){
result = true;
} else {
result = false;
}
Log.e("","responded : "+responded);
return result;
}
But in this situation when I'm still connected to wifi and i'm walking (loosing connection) and press sync button it's still returning true because I'm connected, but actually it's not doing anything.
Is there anyway that I can detect this or I should use connectionTimeOut function in HttpURLConnection class which I'm using?
Actually, I don't know this one solve your problem or not but, you can set connection time-out with your HttpGet request,
This works in my case, So i don't need to check Internet availability..
try
{
HttpGet request = new HttpGet(url));
HttpParams httpParameters = new BasicHttpParams();
// Set the timeout in milliseconds until a connection is established.
// The default value is zero, that means the timeout is not used.
int timeoutConnection = 60000;
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
// Set the default socket timeout (SO_TIMEOUT)
// in milliseconds which is the timeout for waiting for data.
int timeoutSocket = 60000;
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
// create object of DefaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters);
request.addHeader("Content-Type", "application/json");
HttpResponse response = httpClient.execute(request);
// get response entity
HttpEntity entity = response.getEntity();
// convert entity response to string
if (entity != null)
{
result = EntityUtils.toString(entity);
}
}
catch (SocketException e)
{
return "-222" + e.toString();
}
catch (Exception e)
{
return "-333" + e.toString();
}
Note: the request and other code may be different in your case, It just the idea of how HttpGet params used for set Connection TimeOut..
Basically you will receive broadcast when network connectivity changes if you register.
android.net.conn.CONNECTIVITY_CHANGE
For Solution
Here you go.
You will need to register for and handle BroadCastReceiver android.net.conn.CONNECTIVITY_CHANGE
Step 1
Include following permission in manifest
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Step2
Let Android know which class will be register for BroadCast Receiver.
<receiver android:name="ConnectivityReceiver_package_name.ConnectivityReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
Step 3
Put your logic for various Network States.
public class ConnectivityReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
boolean noConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY,false);
if(noConnectivity){
//Show Warning Message
//Take appropriate actions.
}
}
}
try to do it like this:
public static void isNetworkAvailable(final Handler handler, final int timeout)
{
// ask fo message '0' (not connected) or '1' (connected) on 'handler'
// the answer must be send before before within the 'timeout' (in
// milliseconds)
new Thread()
{
private boolean responded = false;
#Override
public void run()
{
// set 'responded' to TRUE if is able to connect with google
// mobile (responds fast)
new Thread()
{
#Override
public void run()
{
HttpGet requestForTest = new HttpGet("http://m.google.com");
try
{
new DefaultHttpClient().execute(requestForTest); // can
// last...
responded = true;
}
catch (Exception e)
{
}
}
}.start();
try
{
int waited = 0;
while (!responded && (waited < timeout))
{
sleep(100);
if (!responded)
{
waited += 100;
}
}
}
catch (InterruptedException e)
{
} // do nothing
finally
{
if (!responded)
{
handler.sendEmptyMessage(0);
}
else
{
handler.sendEmptyMessage(1);
}
}
}
}.start();
}
Handler h = new Handler()
{
#Override
public void handleMessage(Message msg)
{
if (msg.what != 1)
{ // code if not connected
}
else
{ // code if connected
}
}
};
And in your Activity, call it like that:
isNetworkAvailable(h, 2000);
Related
I'm trying to implement a way to listen to a client's connection event on the smartphone hotspot. I see that android.net.wifi.WIFI_HOTSPOT_CLIENTS_CHANGED is no longer avaible. How can i do this? I think that this is possible because the smartphone notify me when i client make a connection to the smartphone hotspot.
You can't use the Intent Action...You have to use a custom method, i'l suggest you create a background thread that checks/reads the I.P table (/proc/net/arp) constantly and update you...here's a snippet I've used.
Read i.p list table
public ArrayList<String> getConnectedDevices() {
ArrayList<String> arrayList = new ArrayList();
try {
BufferedReader bufferedReader = new BufferedReader(new FileReader("/proc/net/arp"));
while (true) {
String readLine = bufferedReader.readLine();
if (readLine == null) {
break;
}
String[] split = readLine.split(" +");
if (split != null && split.length >= 4) {
arrayList.add(split[0]);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return arrayList;
}
Create runnable to check
class CheckHotSpotConnection implements Runnable {
private CheckHotSpotConnection() {
}
public void run() {
int i = 0;
while (discoverClient()) {
i = getConnectedDevices().size();
if (i > 1) {
//client discovered
//disable client discovery to end thread
} else {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
Start Thread
new Thread(new CheckHotSpotConnection()).start();
When I change from wi-fi to 3g or vice versa the my AsyncTask will cause a error. So I want to trace this and restart the loading progress(or stop and proceed the asynctask if possible) when this happens. I looked it up on google and find that the BroadcastReceiver onReceive is called when this happens. The problem now is that I still don't get the exact moment when this happens.
Oncreate
registerReceiver(mConnReceiver,new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
AsyncTask point of error(it's called on the HttpClient line):
#Override
protected String doInBackground(String... params)
{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(params[0]);
try
{
if(!isCancelled())//I have set this after I found the error
{
HttpResponse response = httpclient.execute(httppost);
jsonResult = inputStreamToString(
response.getEntity().getContent()).toString();
}
}
The broadcastreceiver
private BroadcastReceiver mConnReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
boolean noConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
NetworkInfo changes = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
Log.w("current", "" + changes);
if(noConnectivity)
{
task.cancel(true);
task2.cancel(true);
task3.cancel(true);
}
Log.w("taskIsCanceled","" + task.isCancelled());
}
};
So I have two problems tracing the event of the error and restarting or stopping and proceeding the asynctaskes. I have 3 asynctaskes which take turns.
When I switch from 3g to wi-fi the noConnectivity boolean always returns that I have connection. While when I go from wi-fi to 3g it first returns that I dont and shortly after that I have(so that it connected).
You can use reflections to monitor mobile data changes.
public class NetworkStateReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getExtras() != null){
final ConnectivityManager mConnectivityManager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
boolean mobileDataEnabled = false;
try{
Class cmClass = Class.forName(mConnectivityManager.getClass().getName());
Method method = cmClass.getDeclaredMethod("getMobileDataEnabled");
method.setAccessible(true); // Make the method callable
mobileDataEnabled = (Boolean)method.invoke(mConnectivityManager);
} catch(Exception e){
return;
}
Toast.makeText(BackroundService.this, "Data state changed", Toast.LENGTH_LONG).show();
}
}
}
I want to know how could I setup my application to update its details via API post every after 15 minutes. Right now, I knos how to use get and use a thread in order to create a loader for it while accessing the API.
Here's how I do it:
private int authenticateLogin()
{
EditText user = ((EditText)findViewById(R.id.username));
EditText pass = ((EditText)findViewById(R.id.password));
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
String username = user.getText().toString(), password = pass.getText().toString();
String URL = "MyUrl";
String authData = "Basic " + Base64.encodeToString((username + ":" + password).getBytes(), Base64.NO_WRAP);
HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet(URL);
httpget.setHeader("Authorization", authData);
HttpResponse response = null;
try {
response = httpclient.execute(httpget);
StatusLine sl = response.getStatusLine();
int statCode = sl.getStatusCode();
if (statCode == 200) {
String entityStringDrivers = EntityUtils.toString(response.getEntity());
Intent i = new Intent(Login.this,DriverLogin.class);
i.putExtra("stringDrivers", entityStringDrivers);
startActivity(i);
return 100;
}
else
{
user.setText("");
pass.setText("");
Toast.makeText(getBaseContext(), "Unauthorized Login", Toast.LENGTH_SHORT).show();
return 100;
}
} catch (Exception e) {
// Auto-generated catch block
e.printStackTrace();
return 100;
}
finally {
}
}
I want to to know how should I do it when posting and do it in background. I don't know where to start specially with the every 15 minutes POST. Any ideas? Thanks!
You can check this out , and use Intent Services to run in the back ground.
android timer, For intent servicse check it out Intent Services
Use a handler for the timer as follows:
In the snippet call startTimeReqTask() to start your timer.
private Handler m_handler = new Handler();
....
Runnable m_handlerTask = new Runnable() {
#Override
public void run() {
m_handler.postDelayed(m_handlerTask, 900000); // 15 minutes
new authenticateLoginTask().execute(); // POST (your asynctask)
}
};
private void startTimeReqTask() // start timer
{
m_handlerTask.run();
}
private void stopTimeReqTask() // stop time
{
m_handler.removeCallbacks(m_handlerTask);
}
And use AsyncTask authenticateLoginTask for doing it background.
If you want to do this background, create a Service and start it in your main activity's onCreate or some BroadcastReceiver
eg:( You need to add try-catch or other sort of protective code)
public class MyService extends Service {
#Override
public void onStartCommand(Intent intent, int flags, int startId) {
//Use intent to pass your username and password here
//start a PostThread here.
}
private class PostThread extends Thread {
private static final int INTERVAL = 15 * 60 * 1000L;
private boolean canceled = false;
#Override
public void run() {
while (!canceled) {
Post();
Thread.sleep(INTERVAL); // or you can use a Timer to trigger this
}
}
public void interrupt() { canceled = true; super.interrupt();}
}
}
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
// call your api method here
}
});
}
}, 0, /*here define your internal*/);
// when you no longer required this api call just call "cancel" method of timer
My Application drains the battery.I have used services where a request is sent to url.The service is called from my class which extends Application.Below is my code.
public class GApplication extends Application {
private static final String TAG ="GApplication";
private HttpClient httpClient;
private DatabaseHelper databaseHelper;
#Override
public void onCreate(){
super.onCreate();
startService(new Intent(this, GService.class));
httpClient = createHttpClient();
databaseHelper = new DatabaseHelper(this);
}
#Override
public void onLowMemory(){
super.onLowMemory();
shutdownHttpClient();
}
#Override
public void onTerminate(){
super.onTerminate();
stopService(new Intent(this, GService.class));
shutdownHttpClient();
databaseHelper.close();
}
private void shutdownHttpClient(){
if(httpClient != null && httpClient.getConnectionManager() != null){
httpClient.getConnectionManager().shutdown();
}
}
public DatabaseHelper getDatabaseHelper(){
if(databaseHelper == null){
databaseHelper = new DatabaseHelper(this);
}
return databaseHelper;
}
public HttpClient getHttpClient(){
return httpClient;
}
public HttpClient createHttpClient(){
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET);
HttpProtocolParams.setUseExpectContinue(params, true);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
registry.register(new Scheme("https", PlainSocketFactory.getSocketFactory(), 443));
return new DefaultHttpClient(new ThreadSafeClientConnManager(params, registry), params);
}
public boolean isOnline(){
boolean isConnected = false;
try{
ConnectivityManager manager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = manager.getActiveNetworkInfo();
isConnected = (info != null && info.isAvailable() && info.isConnected());
}
catch(Exception e){
isConnected = false;
if(e.getMessage() != null) Log.e(TAG, e.getMessage());
}
return isConnected;
}
}
My Gservice Class
public class GService extends Service {
private static final String TAG = "Gservice";
public IBinder onBind(Intent intent) {
return null;
}
public void onCreate(){
super.onCreate();
Log.i(TAG, "starting GService");
if(isOnline()){
URI uri = URI.create("http://myserver/Android/UploadImage/newAlert.php");
new UpdateCheckAsyncTask(getHttpClient()).execute(uri);
}
}
boolean isOnline(){
return ((GApplication)getApplication()).isOnline();
}
HttpClient getHttpClient(){
return ((GApplication)getApplication()).getHttpClient();
}
DatabaseHelper getDatabaseHelper(){
return ((GApplication)getApplication()).getDatabaseHelper();
}
class UpdateCheckAsyncTask extends WebAsyncTaskBase{
public UpdateCheckAsyncTask(HttpClient httpClient) {
super(httpClient);
}
protected String doInBackground(URI... params) {
return getHttpContent(params[0]);
}
protected void onProgressUpdate(Integer... progress){
}
protected void onPostExecute(String result){
if(result == null){
Log.i(TAG, "Call returned null");
return;
}
try {
Log.i(TAG, "Processsing request");
JSONObject json = new JSONObject(result);
new BlogDbAsyncTask(getDatabaseHelper()).execute(json);
} catch (JSONException e) {
if(e.getMessage() != null) Log.e(TAG, e.getMessage());
}
}
class BlogDbAsyncTask extends DbAsyncTaskBase<JSONObject, Boolean, BlogInfo>{
public BlogDbAsyncTask(DatabaseHelper database) {
super(database);
}
#Override
protected BlogInfo doInBackground(JSONObject... json) {
BlogInfo blogInfo = new BlogInfo();
BlogDAO dao = new BlogDAO(GService.this, getDatabaseHelper());
try {
Log.i(TAG, "Adding new blog entry");
Blog blog = dao.Select(json[0].getInt("FeedId"));
if(blog.UID == null){
blog.UID = json[0].getInt("FeedId");
blog.Text = json[0].getString("Text");
blog.Title = json[0].getString("Header");
blog.PostedOn = json[0].getString("DisplayDate");
blog.PostedBy = "Gservice";
dao.Insert(blog);
blogInfo.Blog = blog;
blogInfo.IsNew = true;
}
} catch (JSONException e) {
if(e.getMessage() != null) Log.e(TAG, e.getMessage());
}
return blogInfo;
}
protected void onPostExecute(BlogInfo result){
}
}
class BlogInfo{
public Blog Blog;
public boolean IsNew;
}
}
Probably the Onterminate method is never called in GApplication class which makes the service run continuously.Please Suggest if any issues can be found with this code.Also Suggest how to stop service if onterminate is never called in device..Thanks in advance.
onTerminate isn't supposed to be called on real devices:
This method is for use in emulated process environments. It will never
be called on a production Android device, where processes are removed
by simply killing them; no user code (including this callback) is
executed when doing so.
you should consider using services instead, and use the appropriate one according to your needs.
if you wish to know when the app was "closed", you need to track the state of the activities. for example, you could have a global counter that counts the number of active activities. for each onCreate, you increase its value. for each onDestroy, you decrease its value. when it reaches 0, it means that no activity is currently active.
however, you should be warned that it's not quite accurate, since activities will be destroyed and re-created when the configuration has changed, so you will need to handle it too.
as i've mentioned, you should consider using a service instead. maybe bind to it on each activity that you need, and unbind when the activity was destroyed. maybe even make it run in the foreground and close it on demand... all depends on your requirements.
You need to use an IntentService instead of Service. This way the service will shut itself down once it completes the task.
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