I have this code:
if (value) {
thread = new Thread() {
#Override
public void run() {
try {
while (!isConnected()) {
synchronized (this) {
wait(3000);
}
}
} catch (InterruptedException ex) {
}
if(wifiManager.isWifiEnabled()){
sendMessageWidget();
} else {
showWifiSettingsAlert();
}
}
};
thread.start();
}
I want my app to wait until google api client is connected and than send a message.
The code for the isConnected method is:
public boolean isConnected() {
mGoogleApiClient.connect();
if (mGoogleApiClient.isConnected()) {
return true;
}
return false;
}
But I get this error message:
NullPointerException: Can't create handler inside thread that has not called Looper.prepare(), and it says that the mistake is somewhere id showWifiSettingsAlert()
here is the code:
public void showWifiSettingsAlert() {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(getActivity());
// Setting Dialog Title
alertDialog.setTitle("Location accuracy tips");
// Setting Dialog Message
alertDialog
.setMessage("You can improve the accuracy of your location by turning on\n- Wi-Fi");
// On pressing Settings button
alertDialog.setPositiveButton("Turn on",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
wifiManager.setWifiEnabled(true);
// Posalji poruke al pre toga jos jednom azuriraj
// lokaciju al ako je pozvana aplikacija iz widgeta
if (value) {
sendMessageWidget();
}
}
});
// on pressing cancel button
alertDialog.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
wifiManager.setWifiEnabled(false);
// Posalji poruke al pre toga jos jednom azuriraj
// lokaciju al ako je pozvana aplikacija iz widgeta
if (value) {
sendMessageWidget();
}
}
});
// Showing Alert Message
alertDialog.show();
}
I want, if wifi is not enabled, the user to choose to enable it or not, but either way the message should be sent... can you help please?
Since you can't touch the UI from a thread other than the main thread, you must post these changes back to the UI thread and its looper and associated handlers. You can do so explicitly by creating a handler associated with the UI thread (which will work anywhere, since Looper.getMainLooper() is a static call) such as:
if (value) {
Handler uiCallback = new Handler(Looper.getMainLooper());
thread = new Thread() {
#Override
public void run() {
try {
while (!isConnected()) {
synchronized (this) {
wait(3000);
}
}
} catch (InterruptedException ex) {
}
uiCallback.post(new Runnable() {
#Override public void run() {
if(wifiManager.isWifiEnabled()){
sendMessageWidget();
} else {
showWifiSettingsAlert();
}
}
});
}
};
thread.start();
}
Or instead of using a handler at all, you can wrap the part in the run() method in runOnUiThread() if you are in an activity which does the same thing.
You should note however, you don't actually need to use any threading here. If you follow the example on: https://developer.android.com/google/auth/api-client.html you'll find that by implementing ConnectionCallbacks, OnConnectionFailedListener you can call mGoogleApis.connect() from the activity's onStart() and when it connects or fails to do the corresponding callback will be executed on the calling thread. For instance,
#Override
public void onConnected(Bundle connectionHint) {
if(wifiManager.isWifiEnabled()){
sendMessageWidget();
} else {
showWifiSettingsAlert();
}
}
Achieves the same thing...
You are using mGoogleApiClient.connect();, which is an asynchronous method, in a thread and this isn't allowed.
You could try using runOnUiThread instead :
runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
//do your stuff here
}
});
Related
Using java (android studio)
I have this thread
void obtenerDatosBackground() {
Thread EnviarCoordenadasHilo = new Thread(new Runnable() {
public void run() {
obtenerDatos();
}
});
statusSync.CheckConnection(EnviarCoordenadasHilo);
}
and I have this in my code:
void configHandler()
{
//con esto le digo al handler que esta adjuntado a la UI
handler = new Handler(Looper.getMainLooper() ){
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
}
but I dont know how to set this handler to the thread.
Finally I use a listener for get result and update the UI but I got this message:
Only the original thread that created a view hierarchy can touch its
views.
I have read (a little) about handler but how can I to set a handler to (non UI) thread for update UI when I got the result
I have change the code to this but it yet dont work
void obtenerDatosBackground()
{
Thread EnviarCoordenadasHilo = new Thread(new Runnable() {
public void run() {
obtenerDatos();
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() { //do what you want to do here
int uno=1;
}
});
}
});
statusSync.CheckConnection(EnviarCoordenadasHilo);
}
REMEMBER
I am using a listener for thread response
void setmListado()
{
adapter = new VehiculoAdapter(getActivity(), mListado);
lvListado.setAdapter(adapter);
lvListado.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
vehicleObject = (Vehiculo) adapter.getItem(i);
edtEconomicNumber=vehicleObject.getNumeroEconomico();
if(mListener!=null)
mListener.onDismissResult(vehicleObject,edtEconomicNumber);
else
Log.w(getTag(),"Falta implementar OnFragmentInteractionListener");
dismiss();
}
});
txtBuscar.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub
//f_car_listado.this.adapter.getFilter().filter(arg0);
//boolean uno=false;
if (count < before) {
// We're deleting char so we need to reset the adapter data
adapter.resetData();
}
adapter.getFilter().filter(s.toString());
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
}
});
}
here I got the responde from thread
#Override
public void onFragmentFinished(boolean terminoBien, List<VehiculoResponseDTO> listado) {
dialogFragment.dismiss();
if(terminoBien)
{
if(listado.size()>0) {
mListado = ListadoDTOaVehiculos(listado);
//adapter = new VehiculoAdapter(getActivity(), mListado);
//lvListado.setAdapter(adapter);
setmListado();
//adapter.notifyDataSetChanged();
}
else {
this.dismiss();
f_seguimiento.DialogMensaje(getString(R.string.nohayvehiculos), getString(R.string.nohayvehiculosMensaje), true, null, getActivity());
}
}else
{
this.dismiss();
f_seguimiento.DialogMensaje(getString(R.string.ocurrioProblema),getString(R.string.errorVehiculos),true,null,getActivity());
}
}
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
//do what you want to do here
}
});
I finally solved with this Video:
and this is the code in simply steps:
this is my handler
void configHandler()
{
//con esto le digo al handler que esta adjuntado a la UI
handler = new Handler(Looper.getMainLooper() ){
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
setmListado();
}
};
}
I call configHandler on Oncreate
and on my listener (Remember it's running on (Non ui) Thread)
#Override
public void onFragmentFinished(boolean terminoBien, List<VehiculoResponseDTO> listado) {
dialogFragment.dismiss();
if(terminoBien)
{
if(listado.size()>0) {
mListado = ListadoDTOaVehiculos(listado);
//adapter = new VehiculoAdapter(getActivity(), mListado);
//lvListado.setAdapter(adapter);
Message message =Message.obtain();
handler.sendMessage(message);
//adapter.notifyDataSetChanged();
}
else {
this.dismiss();
f_seguimiento.DialogMensaje(getString(R.string.nohayvehiculos), getString(R.string.nohayvehiculosMensaje), true, null, getActivity());
}
}else
{
this.dismiss();
f_seguimiento.DialogMensaje(getString(R.string.ocurrioProblema),getString(R.string.errorVehiculos),true,null,getActivity());
}
}
these lines:
Message message =Message.obtain();
handler.sendMessage(message);
call the code inside configHandler()
explicitly these lines:
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
setmListado();
}
but what it work? because when handleMessage is call it is on UI thread and no in (Non UI) thread
in configHandler()
in this line using Looper.getMainLooper() I set this handler belongs to UI Thread
handler = new Handler(Looper.getMainLooper() )
I have to update the list after optimizing the running apps ....
m_optimizeBtn.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
launchProgressRing(OptimizationActivity.this);
listAdaptor.notifyDataSetChanged();
}
});
}
Killing the running process in a seprate thread....
public void launchProgressRing(Context ctx){
final ProgressDialog opt_proDialog=new ProgressDialog(ctx);
opt_proDialog.setTitle("Please wait...");
opt_proDialog.setMessage("Optimizing power draining apps...");
opt_proDialog.setIndeterminate(true);
opt_proDialog.show();
opt_proDialog.setCancelable(false);
new Thread(new Runnable()
{
#Override
public void run()
{
//TODO: optimize apps
m_cPowerDrainingApps.killBgRunningProcesses(runningAppsList);
try
{
Thread.sleep(1500);
} catch (InterruptedException e)
{
e.printStackTrace();
}
runOnUiThread(new Runnable()
{
#Override
public void run()
{
opt_proDialog.dismiss();
}
});
}
}).start();
}
listAdaptor.notifyDataSetChanged() is not working ,don't know why ???
What I suggest is to use AsyncTask to do the job. AsyncTask has two good methods for you:
doInBackground: which you can put most of the background tasks in there
onPostExecute : which you can put the logic of what needs to be done when the background task has finished its job.
So your code should look like this:
public class BackgroundTask extends AsyncTask<Void,Void,Void>{
private ListAdapter mAdapter;
public BackgroundTask(ListAdapter adapter)
{
mAdapter = adapter
}
public Void doInBackground (Void... params)
{
//define m_cPowerDrainingApps somewhere
m_cPowerDrainingApps.killBgRunningProcesses(runningAppsList);
try
{
Thread.sleep(1500);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
public Void onPostExecute (Void... params)
{
//do your UI things
mAdapter.notifyDataSetChanged();
}
}
and then run this with:
new BackgroundTask(listAdapter).execute()
Use a Handler and its postDelayed method to invalidate the list's adapter as follows:
final Handler handler = new Handler()
handler.postDelayed( new Runnable() {
#Override
public void run() {
adapter.notifyDataSetChanged();
handler.postDelayed( this, 60 * 1000 );
}
}, 60 * 1000 );
You must only update UI in the main (UI) thread.
I got 3 activities ( A , B ,C ) and a service that I call to check if I got new messages from DB. It's a HTTP request . I need to make the request each 15 sec.
Thread t = new Thread() {
#Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(15000);
runOnUiThread(new Runnable() {
#Override
public void run() {
// Here i call
}
});
}
} catch (InterruptedException e) {
}
}
};
t.start();
How to make it work when i am changing activities ?
Option: Consider changing setup to have three fragments as your original activities, and a MainActivity that controls the repeat polling for messages to DB, as well as controlling the fragments.
#SuppressLint("SimpleDateFormat")
public class AlarmService extends Service {
private PendingIntent pendingIntent;
Handler mHandler;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
}
public void f() {
Toast t = Toast.makeText(this, "Service is still running",
Toast.LENGTH_SHORT);
t.show();
};
}
#Override
#Deprecated
public void onStart(Intent intent, int startId) {
Toast t = Toast.makeText(this, "Service started", Toast.LENGTH_SHORT);
t.show();
// TODO Auto-generated method stub
super.onStart(intent, startId);
mHandler = new Handler();
Runnable r = new Runnable() {
#Override
public void run() {
f();
mHandler.postDelayed(this, 20000);
}
};
mHandler.postDelayed(r, 20000);
}
}
and in manifest use this
<service android:name="com.example.yourservice"></service>
I want to display an alert dialog depending upon the property and when the user clicks on the OK button, call the function again to get updated values within the running process.
I have the following code:
importingProgress = ProgressDialog.show(context, getString(R.string.progressNewsListTitle),
getString(R.string.progressProjectListMessage), true);
new Thread(new Runnable() {
public void run() {
try {
app.SetOtherTaskRunning(true);
Ib_clients client = db.Ib_clients_GetById(app.GetCustomerId());
try {
LogManager.WriteToFile("---------------- Getting News from Webservice :- " + DateFormat.getDateTimeInstance().format(new Date()) + "----------------");
CommonFuctions.CreateXml(context, h, client, db, app.GetBookMonth(), app.GetBookQuater(), app.GetBookYear(), Constants.News, app.GetWebServiceLastSyncDate(Constants.ServiceType.NEWS.toString()), Constants.ServiceType.NEWS, null, null, null, null, null);
Return reponse = null;
do {
reponse = CommonFuctions.SendingRequest(context, handler, db);
if (reponse.type.compareTo("warning") == 0) {
h.post(new Runnable() {
public void run() {
AlertDialog.Builder alert = new AlertDialog.Builder(context);
alert.setTitle(context.getString(R.string.information));
alert.setMessage("dsgdgd");
alert.setPositiveButton(context.getString(R.string.logoutDialogOk), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
}
});
alert.show();
}
});
}
} while (reponse.type.compareTo("warning") == 0);
} catch (IOException e) {
e.printStackTrace();
}
} catch (Exception e) {
//Log.d(Constants.TAG, e.getMessage());
e.printStackTrace();
}
if (importingProgress != null) {
importingProgress.dismiss();
importingProgress = null;
}
}
}).start();
If response type is warning, then display a message to the user and if the user clicks the OK button , then call CommonFuctions.SendingRequest(context, handler, db) again to get updated values. Until we get a.response type of warning , we need to display an alert dialog to the user and call CommonFuctions.SendingRequest(context, handler, db) again.
Class to return:
public class Return {
public String type;
public String msg;
public boolean isSuccess;
public int client_id; // for getting clientid from server
public int booking_id; // for getting bookingid form server
}
You will have to use handler to display the AlertDialog because UI can be handled by the main thread only.
The other way is to use asyncTask for multiprocessing and then using the onPostExcecute() of asyncTask to display the AlertDialog
Please feel free to ask any further doubts.
Try to run your dialog as below in runonUIthread:
runOnUiThread(new Runnable() {
#Override
public void run() {
AlertDialog.Builder alert = new AlertDialog.Builder(context);
alert.setTitle(context.getString(R.string.information));
alert.setMessage("dsgdgd");
alert.setPositiveButton(context.getString(R.string.logoutDialogOk), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
}
});
alert.show();
}
});
I get this error "Can't create handler inside thread that has not called Looper.prepare()"
Can you tell me how to fix it?
public class PaymentActivity extends BaseActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.payment);
final Button buttonBank = (Button) findViewById(R.id.buttonBank);
buttonBank.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
progressDialog = ProgressDialog.show(PaymentActivity.this, "",
"Redirecting to payment gateway...", true, true);
new Thread() {
public void run() {
try {
startPayment("Bank");
} catch (Exception e) {
alertDialog.setMessage(e.getMessage());
handler.sendEmptyMessage(1);
progressDialog.cancel();
}
}
}.start();
}
});
StartPayment Method:
private void startPayment(String id) {
Bundle b = getIntent().getExtras();
final Sail sail = b.getParcelable(Constant.SAIL);
final Intent bankIntent = new Intent(this, BankActivity.class);
try {
Reservation reservation = RestService.createReservation(
sail.getId(),
getSharedPreferences(Constant.PREF_NAME_CONTACT, 0));
bankIntent.putExtra(Constant.RESERVATION, reservation);
// <workingWithDB> Storing Reservation info in Database
DBAdapter db = new DBAdapter(this);
db.open();
#SuppressWarnings("unused")
long rowid;
rowid = db.insertRow(sail.getId(), sail.getFrom(),
sail.getTo(), sail.getShip(), sail.getDateFrom().getTime(),
sail.getPrice().toString(), reservation.getId().floatValue());
db.close();
// </workingWithDB>
String html = PaymentService.getRedirectHTML(id, reservation);
bankIntent.putExtra(Constant.BANK, html);
} catch (Exception e) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
AlertDialog alertDialog = builder.create();
alertDialog.setMessage(e.getMessage());
alertDialog.show();
}
startActivity(bankIntent);
}
You should know that when you try to modify your UI , the only thread who can do that is the UiThread.
So if you want to modify your UI in another thread, try to use the method: Activity.runOnUiThread(new Runnable);
Your code should be like this :
new Thread() {
public void run() {
YourActivity.this.runOnUiThread(new Runnable(){
#Override
public void run(){
try {
startPayment("Bank");//Edit,integrate this on the runOnUiThread
} catch (Exception e) {
alertDialog.setMessage(e.getMessage());
handler.sendEmptyMessage(1);
progressDialog.cancel();
}
});
}
}
}.start();
I assume you create a Handler in startPayment() method. You can't do that, as handlers can be created on th UI thread only. Just create it in your activity class.
Instead of new Thread() line, try giving
this.runOnUiThread(new Runnable() {
you cant change any UI in thread you can use runOnUIThread or AsyncTask for more detail about this click here
I've found that most thread handling can be replaced by AsyncTasks like this:
public class TestStuff extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button buttonBank = (Button) findViewById(R.id.button);
buttonBank.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
new StartPaymentAsyncTask(TestStuff.this).execute((Void []) null);
}
});
}
private class StartPaymentAsyncTask extends AsyncTask<Void, Void, String> {
private ProgressDialog dialog;
private final Context context;
public StartPaymentAsyncTask(Context context) {
this.context = context;
}
#Override
protected void onPreExecute() {
dialog = new ProgressDialog(context);
// setup your dialog here
dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
dialog.setMessage(context.getString(R.string.doing_db_work));
dialog.setCancelable(false);
dialog.show();
}
#Override
protected String doInBackground(Void... ignored) {
String returnMessage = null;
try {
startPayment("Bank");
} catch (Exception e) {
returnMessage = e.getMessage();
}
return returnMessage;
}
#Override
protected void onPostExecute(String message) {
dialog.dismiss();
if (message != null) {
// process the error (show alert etc)
Log.e("StartPaymentAsyncTask", String.format("I received an error: %s", message));
} else {
Log.i("StartPaymentAsyncTask", "No problems");
}
}
}
public void startPayment(String string) throws Exception {
SystemClock.sleep(2000); // pause for 2 seconds for dialog
Log.i("PaymentStuff", "I am pretending to do some work");
throw new Exception("Oh dear, database error");
}
}
I pass in the Application Context to the Async so it can create dialogs from it.
The advantage of doing it this way is you know exactly which methods are run in your UI and which are in a separate background thread. Your main UI thread isn't delayed, and the separation into small async tasks is quite nice.
The code assumes your startPayment() method does nothing with the UI, and if it does, move it into the onPostExecute of the AsyncTask so it's done in the UI thread.
Try
final Handler handlerTimer = new Handler(Looper.getMainLooper());
handlerTimer.postDelayed(new Runnable() {
public void run() {
......
}
}, time_interval});