Reputation: 5302
Im getting that famous "Can't create handler inside thread that has not called Looper.prepare()" error in my below code. based on most of my Google search result, this happens when i try to update UI from my none-ui-thread, but im not updating the UI at this point when i call the method from my other helper class (only after address has been returned); so please consult on why this is happening would be appreciated.
package com.parspake.kookojapost;
import android.app.ActionBar;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.location.*;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class TextShare extends Activity {
ConnectionHandler textPageConn;
TextView dt2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.text_share);
textPageConn = new ConnectionHandler(this);
dt2 = (TextView) findViewById(R.id.show_location_text_page);
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
textPageConn.getLocation();
do {
if (textPageConn.mAddress != null) {
dt2.setText(textPageConn.mAddress);
break;
} else {
Log.d("debug","no location");
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
} while (textPageConn.mAddress == null);
}
});
thread1.start();
}
}
this is the exception that i get:
07-04 23:59:38.730: E/AndroidRuntime(7149): FATAL EXCEPTION: Thread-8482
07-04 23:59:38.730: E/AndroidRuntime(7149): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
07-04 23:59:38.730: E/AndroidRuntime(7149): at android.os.Handler.<init>(Handler.java:121)
07-04 23:59:38.730: E/AndroidRuntime(7149): at android.location.LocationManager$ListenerTransport$1.<init>(LocationManager.java:183)
07-04 23:59:38.730: E/AndroidRuntime(7149): at android.location.LocationManager$ListenerTransport.<init>(LocationManager.java:183)
07-04 23:59:38.730: E/AndroidRuntime(7149): at android.location.LocationManager._requestLocationUpdates(LocationManager.java:661)
07-04 23:59:38.730: E/AndroidRuntime(7149): at android.location.LocationManager.requestLocationUpdates(LocationManager.java:486)
07-04 23:59:38.730: E/AndroidRuntime(7149): at com.parspake.kookojapost.ConnectionHandler.getLocation(ConnectionHandler.java:136)
07-04 23:59:38.730: E/AndroidRuntime(7149): at com.parspake.kookojapost.TextShare$2.run(TextShare.java:69)
07-04 23:59:38.730: E/AndroidRuntime(7149): at java.lang.Thread.run(Thread.java:856)
so ConnectionHandler.java:136 is -> mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 50, mlocationListener);
and TextShare.java:69 is -> textPageConn.getLocation();
this is my ConnectionHandler Helper class:
package com.parspake.kookojapost;
import android.content.Context;
import android.location.*;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
public class ConnectionHandler {
private Context ctx;
double mLat;
double mLong;
String currCity;
String currCountry;
String mAddress;
LocationManager mLocationManager;
LocationListener mlocationListener;
public ConnectionHandler(Context context) {
this.ctx = context;
}
public boolean locationSourceEnabled() {
mLocationManager = (LocationManager) ctx.getSystemService(Context.LOCATION_SERVICE);
boolean isInternetLocationAvailable = mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
boolean isGpsAvailable = mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (isInternetLocationAvailable) {
return true;
} else if (isGpsAvailable) {
return true;
}
return false;
}
public void getLocation() {
mlocationListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
mLat = location.getLatitude();
mLong = location.getLongitude();
Geocoder gcd = new Geocoder(ctx, Locale.getDefault());
List<Address> addresses;
try {
addresses = gcd.getFromLocation(mLat, mLong, 1);
if (addresses.size() > 0) {
currCity = addresses.get(0).getLocality();
currCountry = addresses.get(0).getCountryName();
mAddress = currCity + " - " + currCountry;
}
} catch (IOException e) {
Log.d("omid debug", e.getMessage());
}
}
@Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
@Override
public void onProviderEnabled(String s) {
}
@Override
public void onProviderDisabled(String s) {
}
};
mLocationManager = (LocationManager) ctx.getSystemService(Context.LOCATION_SERVICE);
if (locationSourceEnabled()) {
if (mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 10000, 50, mlocationListener);
}
if (mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 50, mlocationListener);
}
}
}
}
Upvotes: 0
Views: 6547
Reputation: 4567
Ok the problem is that requestLocationUpdates is an asynchronous call, meaning that you don't need to run it on another thread and also means if you try to you are effectively making a handler on another thread which is not allowed. So instead you can remove the thread and just run this all on onCreate() (since you are only doing async calls)
Instead you could put your syncronous calls in another thread...
@Override
public void onLocationChanged(Location location) {
new Thread(new Runnable() {
@Override
public void run() {
mLat = location.getLatitude();
mLong = location.getLongitude();
Geocoder gcd = new Geocoder(ctx, Locale.getDefault());
List<Address> addresses;
try {
addresses = gcd.getFromLocation(mLat, mLong, 1);
if (addresses.size() > 0) {
currCity = addresses.get(0).getLocality();
currCountry = addresses.get(0).getCountryName();
mAddress = currCity + " - " + currCountry;
}
} catch (IOException e) {
Log.d("omid debug", e.getMessage());
}
}
}).start();
}
Upvotes: 2
Reputation: 1188
Its not possible to change the ui content in other thread.. you can solve these problem in basically 2 ways
I'll suggest to use handler with callback method. You can get great tutorial here. handler with callback in thread
Upvotes: 0
Reputation: 62209
You can't update TextView
from non-UI thread.
Use runOnUiThread
instead:
runOnUiThread(new Runnable() {
@Override
public void run() {
dt2.setText(textPageConn.mAddress);
}
});
Upvotes: 1