How to display alert dialog in running thread? - java

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();
}
});

Related

Making own Alert dialogs extending AppCompatDialogFragment

I am trying to make my own Alert dialogs using "utility" class that extends AppCompatDialogFragment. But when I try to set my own messages, they didn't change, but the default ones of the class I created continue to appear.
For example in my AlertDialogConnection class I made Override of onCreateDialog, but in my activity, while I perform http request, I can't make my own texts.
My own class that extends AppCompatDialogFragment
public class AlertDialogConnection extends AppCompatDialogFragment {
private Builder builder;
private String title;
private String text;
public AlertDialogConnection(){
this.builder = null;
this.text = "";
this.title = "";
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
if((this.title == "") || (this.text == "") || (this.builder == null)){
this.builder = new Builder(getActivity());
this.builder.setTitle("Error");
this.builder.setMessage("Default Error: Error! try later");
this.builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
System.exit(0);
}
});
}else {
this.builder = new Builder(getActivity());
this.builder.setTitle(this.title);
this.builder.setMessage(this.text);
this.builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
System.exit(0);
}
});
}
return builder.create();
}
public void setTitle(String title){
this.title = title;
}
public void setText(String text){
this.text = text;
}
}
Some code using that class
in this class, in case of error I continue to see the default error of the class AlertDialogConnection, instead of my serverError title and text.
private AlertDialogConnection serverError = new AlertdialogConnection();
private void requestData(String url) throws MalformedURLException {
Request request = new Request.Builder().url(url).build();
final Intent intent = new Intent(this, ModelResultData.class);
httpClient.connectTimeoutMillis(); //server timeout
httpClient.writeTimeoutMillis();
httpClient.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
Log.d("HTTP-Error", "HTTP request error!");
AlertDialogConnection errorDialog = new AlertDialogConnection();
errorDialog.setTitle("server error!");
errorDialog.setText("server messaging error, try later");
errorDialog.show(getSupportFragmentManager(), "messaging error!");
//Toast.makeText(getApplicationContext(), "results not found", Toast.LENGTH_LONG).show();
}
#Override
public void onResponse(#NotNull Call call, Response response) throws IOException {
if(response.isSuccessful()){
/* HTTP-code: 200 */
final String body = response.body().string();
ModelSearchActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
intent.putExtra("ACTIVITY_SOURCE", "ModelSearchActivity");
intent.putExtra("json_data", body);
startActivity(intent);
}
});
}else{
//System.out.println(response.code());
//if (response.code() == 403) {
//Toast.makeText(getApplicationContext(), "results not found", Toast.LENGTH_LONG).show();
//} else if (response.code() == 500) {
/* Http-code: 500 */
Log.d("HTTP-Error", "server error!");
serverError.setTitle("server error!");
serverError.setText("server error, try later");
serverError.show(getSupportFragmentManager(), "server error!");
//}
}
}
});
}
I have tried making comparisons with response code, but nothing change.
The default value (in the constructor) you've set for builder is null.
This causes it to always get through the if condition since builder == null would return true. Try something along the following lines,
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
this.builder = new Builder(getActivity());
if(this.title.isEmpty() || this.text.isEmpty()){
this.builder.setTitle("Error");
this.builder.setMessage("Default Error: Error! try later");
this.builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
System.exit(0);
}
});
}else {
this.builder.setTitle(this.title);
this.builder.setMessage(this.text);
this.builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
System.exit(0);
}
});
}
return builder.create();
}
You don't need to have a separate utility for creating your own alert dialogue you can simply create a view and use the setView method to show that view in your app. See the snippet below
private void showDialog()
{
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
View view = getLayoutInflater().inflate(R.layout.sortdialog,null);//Replace it
alertDialogBuilder.setView(view);
alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
This will allow you to create custom alert dialog boxes using the layout which you have created

How can I stop same alert dialog showing every time from handler?

I have an AlertDialog on a method and the method is used inside a Handler. When the Handler running every time the AlertDialog also loading again and again, I want to show the dialog one time if the dialog is still showing I don't want to load it again. For this I have the below code but not working.
Handler handler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run() {
handler.postDelayed(this, 1000);
checkCountry();
}
};
handler.postDelayed(runnable, 1000);
public void checkCountry() {
alertDialogueBuilder = new AlertDialog.Builder(MainActivity.this);
alertDialogueBuilder.setTitle("VPN Detected!");
alertDialogueBuilder.setMessage("Please Turn Of VPN To Continue!");
alertDialogueBuilder.setIcon(R.drawable.errorstop);
alertDialogueBuilder.setCancelable(false);
alertDialogueBuilder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
AlertDialog alertDialog = alertDialogueBuilder.create();
if(alertDialog.isShowing()){
//Do Something
}else{
alertDialog.show();
}
}
Create your Dialog only once and not every time:
private AlertDialog alertDialog;
// ...
initDialog();
Handler handler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run() {
handler.postDelayed(this, 1000);
checkCountry();
}
};
handler.postDelayed(runnable, 1000);
//...
public void initDialog() {
alertDialogueBuilder = new AlertDialog.Builder(MainActivity.this);
alertDialogueBuilder.setTitle("VPN Detected!");
alertDialogueBuilder.setMessage("Please Turn Of VPN To Continue!");
alertDialogueBuilder.setIcon(R.drawable.errorstop);
alertDialogueBuilder.setCancelable(false);
alertDialogueBuilder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
alertDialog = alertDialogueBuilder.create();
}
public void checkCountry() {
if(alertDialog.isShowing()){
//Do Something
}else{
alertDialog.show();
}
}
To show only 1-time dialog call only this checkCountry() method from which you want to show this dialog. And, please remove the Handler code. No need to use Handler here. Use only checkCountry() method to show the dialog.
The oldest trick in the book is to just make a boolean field "isAlertDialogShown" with false initialization, upon creation to true and in the onClick set it to false again (if you want it to be shown again when the handler fires).
private boolean isShown = false;
public void checkCountry() {
if (isShown){
//do something
return;
}
isShown = true;
alertDialogueBuilder = new AlertDialog.Builder(MainActivity.this);
alertDialogueBuilder.setTitle("VPN Detected!");
alertDialogueBuilder.setMessage("Please Turn Of VPN To Continue!");
alertDialogueBuilder.setIcon(R.drawable.errorstop);
alertDialogueBuilder.setCancelable(false);
alertDialogueBuilder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
isShown = false;
finish();
}
});
AlertDialog alertDialog = alertDialogueBuilder.create();
alertDialog.show();
}
if you want to try and use the alertDialog isShowing you need to use the one you created and not the new one, so again save it as a field,
but you will still might have an edge case if the handler timer is running too fast, and that is alertDialog.show() is not an immediate operation:
AlertDialog alertDialog;
public void checkCountry() {
if ( alertDialog != null && alertDialog.isShowing){
//do something
return;
}
alertDialogueBuilder = new AlertDialog.Builder(MainActivity.this);
alertDialogueBuilder.setTitle("VPN Detected!");
alertDialogueBuilder.setMessage("Please Turn Of VPN To Continue!");
alertDialogueBuilder.setIcon(R.drawable.errorstop);
alertDialogueBuilder.setCancelable(false);
alertDialogueBuilder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
alertDialog = alertDialogueBuilder.create();
alertDialog.show();
}

Using Thread in Android for sending message

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
}
});

button.PerformClick() causing text to clear

I have an activity where a user sends messages to another user, I created an onKey listener to send messages when a user pressed enter as well.
When a user actually clicks the send button, everything works perfectly, when a user presses the enter button a blank message is sent.
Here is the onkeylistener code
Code:
messageText.setOnKeyListener(new OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == 66) {
sendMessageButton.performClick();
return true;
}
return false;
}
});
and this is the sendmessagebutton
Code:
sendMessageButton.setOnClickListener(new OnClickListener() {
CharSequence message;
Handler handler = new Handler();
#Override
public void onClick(View arg0) {
// android.text.format.DateFormat df = new
// android.text.format.DateFormat();
message = messageText.getText();
String messageSent = DateFormat.format("dd MMM yy, kk:mm",
new java.util.Date()).toString();// java.text.DateFormat.getDateTimeInstance().format("yyyy-MM-dd kk:mm:ss");
if (message.length() > 0) {
appendToMessageHistory(imService.getUsername(),
message.toString(), messageSent);
((ScrollView) findViewById(R.id.scrollView))
.fullScroll(View.FOCUS_DOWN);
localstoragehandler.insert(imService.getUsername(),
friend.userName, message.toString(), messageSent);
messageText.setText("");
Thread thread = new Thread() {
#Override
public void run() {
try {
if (imService.sendMessage(
imService.getUsername(),
friend.userName, message.toString()) == null) {
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(
getApplicationContext(),
R.string.message_cannot_be_sent,
Toast.LENGTH_LONG).show();
// showDialog(MESSAGE_CANNOT_BE_SENT);
}
});
}
} catch (UnsupportedEncodingException e) {
Toast.makeText(getApplicationContext(),
R.string.message_cannot_be_sent,
Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
};
thread.start();
}
}
});
When user clicks button
message = messageText.getText();// get message
Then you do
messageText.setText("");
So when user presses the enter button in onKey you have sendMessageButton.performClick() a blank message is sent since you already set messageText.setText("")

Android Progressbar starts at the wrong time

I try to launch a progressbar in my application but wehn I launch it the BAr isn't show before the function is started
public void onClick(View v) {
if (v == button)
{
ProgressDialog dialog = ProgressDialog.show(App.this, "",
"Loading. Please wait...", true);
dialog.show();
try
{
directory = edittext.getText().toString();
FileWriter fstream = new FileWriter("/data/data/folder.hide.alexander.fuchs/folder.db");
BufferedWriter out = new BufferedWriter(fstream);
out.write(directory);
//Close the output stream
out.close();
if(hide_or_show == "hide")
{
edittext.setVisibility(View.INVISIBLE);
folder_to_hide.setVisibility(View.INVISIBLE);
hide();
dialog.dismiss();
}
else
{
show();
edittext.setVisibility(View.VISIBLE);
folder_to_hide.setVisibility(View.VISIBLE);
dialog.dismiss();
}
}
catch(Exception x)
{
String ErrorMessage = x.getMessage();
Toast.makeText(this,"Error"+ErrorMessage, Toast.LENGTH_LONG).show();
finish();
}
}
if (v == options)
{
final CharSequence[] items = {"Change password", "http://www.alexander-fuchs.net/", "Market"};
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Options");
builder.setItems(items, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
if (items[item] == "Change password")
{
createpass();
}
if (items[item] == "http://www.alexander-fuchs.net/")
{
intentstarter(items[item].toString());
toaster(items[item].toString());
}
if (items[item] == "Market")
{
intentstarter("market://search?q=pub:Alexander Fuchs");
toaster("Please wait...");
}
}
});
AlertDialog alert = builder.create();
alert.show();
}
}
when I tap the button it takes long to respond and then the whole function finishs without prompting an progressbar
onClickis a callback where the return to Android is only returned when the callback ends.
All UI interaction you do basically is collected and queued while the callback is active and executed after return (may not technically totally accurate).
For you ProgressBar to show up at the start of the action and vanish at the end, you can implement an AsyncTask where the progress bar is shown in onPreExecute, the real computation is done in doInBackground and the progressbar is dismissed in onPostExecute. For example:
protected void onPreExecute() {
dialog = new ProgressDialog(context);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.show();
}
protected void onPostExecute(Map<Integer, String> integerStringMap) {
if (dialog!=null)
dialog.cancel();
}
protected void onProgressUpdate(Integer... values) {
int val = values[0]*10000/num;
dialog.setProgress(val);
}
See here for the more complete example.

Categories