Android: Simplest Internet connection dialog with Retry/Cancel - java

I am stuck in implementing a dialog which checks for internet connectivity as soon as the app is opened (i.e. in onCreate()). However, I moved the dialog code to a different class to keep the MainActivity clean.
I need to check for connectivity everytime the user clicks retry, show the dialog again if internet is not present else call the onRefresh() method present in the MainActivity class.
The code looks something like this:
public static boolean showNoConnectionDialog(final Context c) {
if(checkConnectivity(c))
{
result = true;
return result;
}
else
{
AlertDialog.Builder b =new AlertDialog.Builder(c);
b.setTitle("No Connection");
b.setMessage("Cannot connect to the internet!");
b.setPositiveButton("Retry", new AlertDialog.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if(!checkConnectivity(c))
showNoConnectionDialog(c);
else
{
result = true;
}
}
});
b.setNegativeButton("Exit", new AlertDialog.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
((Activity)c).finish();
}
});
b.create().show();
}
return result;
}
private static Boolean checkConnectivity(Context c) {
ConnectivityManager cm = (ConnectivityManager) c.getSystemService(Context.CONNECTIVITY_SERVICE);
// test for internet connection
if (cm.getActiveNetworkInfo() != null && cm.getActiveNetworkInfo().isAvailable() && cm.getActiveNetworkInfo().isConnected())
return true;
else
return false;
}
In the MainActivity, I tried:
if(DialogBoxes.showNoConnectionDialog(this)){
onRefresh();
}
However, clicking the Retry button after connecting to the internet does nothing, since the "if" part is checked only once. Using while instead of if causes the UI to stop responding.
What do I do ?

First declare your AlertDialog outside of any method but inside of your class:
AlertDialog dialog;
Then inside of your positive button listener:
b.setPositiveButton("Retry", new AlertDialog.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if(!checkConnectivity(c))
dialog.show();
else
{
result = true;
}
}
});
dialog = b.create();
dialog.show();

Related

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

Detect Back Button Event when Dialog is Open

I'm building an app that has 2 dialogues that open up and I want something to occur if the user presses the back button while certain dialogues are open. However, for some reason, the back button event is not registering when the dialogues are open. I tested it by putting a log in onBackPressed() and whenever the dialogues are NOT open and I'm simply on the main activity, the logs appear on logcat. However, if the dialogues are open, I simply get this:
W/InputEventReceiver: Attempted to finish an input event but the input event receiver has already been disposed.
Below I have placed the code for the dialogues:
public void pair() {
final Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
AlertDialog.Builder pairedList = new AlertDialog.Builder(this);
pairedList.setTitle("Paired Devices");
final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.select_dialog_singlechoice);
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
arrayAdapter.add(device.getName());
}
}
pairedList.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
mBluetoothAdapter.disable();
// pair_dialog = false;
}
});
pairedList.setPositiveButton("Pair New", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
startActivityForResult(new Intent(android.provider.Settings.ACTION_BLUETOOTH_SETTINGS), 0);
}
});
pairedList.setAdapter(arrayAdapter, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// connect_dialog = true;
String strName = arrayAdapter.getItem(which);
AlertDialog.Builder builderInner = new AlertDialog.Builder(MainActivity.this);
builderInner.setMessage(strName);
builderInner.setTitle("Connect To:");
builderInner.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
for (BluetoothDevice device : pairedDevices) {
if(device.getName().equals(strName)){
paired = device;
dialog.dismiss();
}
}
}
});
builderInner.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// connect_dialog = false;
pairedList.show();
}
});
builderInner.show();
}
});
pairedList.show();
// pair_dialog = true;
}
Below is my onBackPressed() method which is right after the above method. Nothing out of the ordinary, I don't think.
#Override
public void onBackPressed() {
Log.e(TAG, "Back Button Pressed");
super.onBackPressed();
}
Like I said, if the dialogues are not open, the log shows up just fine in logcat but if the dialogues are open, it's like the back button doesn't register.
this worked for me...
yuordialog.setOnKeyListener(new Dialog.OnKeyListener() {
#Override
public boolean onKey(DialogInterface arg0, int keyCode,
KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
//your stuff....
}
return true;
}
});
If you have added,
dialog.setCancelable(false);
change it to,
dialog.setCancelable(true);
Actually, setCancelable(false) cancel the event of touch outside the dialog and back press also.
You can also use
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialogInterface) {
//your dismiss code here
}
});
This listens to both backpress events and dismiss by touch.

Deitel How to program Android Cannon Game anonymous inner class warning

I'm coding through Deitel: Android How to program examples and in two of them my Android Studio gives warning/error on anonymous inner classes. It declares that Fragments should be static.
What's the correct way to go through this? If I make static non-anonymous inner class then there is no warning about the class, but I can't reference to non-static class variables(?). Other way could be to make a separate class (not inner class), but there is same problem with referencing variables.
This problem in with example Cannon Game, class CannonView, method showGameOverDialog (below) and also on FlagQuiz.
private void showGameOverDialog(final int messageId) {
final DialogFragment gameResult =
new DialogFragment() {
#Override
public Dialog onCreateDialog(Bundle bundle) {
AlertDialog.Builder builder =
new AlertDialog.Builder(getActivity());
builder.setTitle(getResources().getString(messageId));
builder.setMessage(getResources().getString(
R.string.result_format, shotsFired, totalElapsettime
));
builder.setPositiveButton(R.string.reset_game,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialogIsDisplayed = false;
newGame();
}
});
return builder.create();
}
};
activity.runOnUiThread(
new Runnable() {
#Override
public void run() {
showSystemBars();
dialogIsDisplayed = true;
gameResult.setCancelable(false);
gameResult.show(activity.getFragmentManager(), "results");
}
}
);
}
// display an AlertDialog when the game ends
private void showGameOverDialog(final int messageId) {
// DialogFragment to display game stats and start new game
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(getResources().getString(messageId));
// display number of shots fired and total time elapsed
builder.setMessage(getResources().getString(
R.string.results_format, shotsFired, totalElapsedTime));
builder.setPositiveButton(R.string.reset_game,
new DialogInterface.OnClickListener() {
// called when "Reset Game" Button is pressed
#Override
public void onClick(DialogInterface dialog,
int which) {
dialogIsDisplayed = false;
newGame(); // set up and start a new game
}
}
);
/* final DialogFragment gameResult =
new DialogFragment() {
// create an AlertDialog and return it
#Override
public Dialog onCreateDialog(Bundle bundle) {
// create dialog displaying String resource for messageId
AlertDialog.Builder builder =
new AlertDialog.Builder(getActivity());
builder.setTitle(getResources().getString(messageId));
// display number of shots fired and total time elapsed
builder.setMessage(getResources().getString(
R.string.results_format, shotsFired, totalElapsedTime));
builder.setPositiveButton(R.string.reset_game,
new DialogInterface.OnClickListener() {
// called when "Reset Game" Button is pressed
#Override
public void onClick(DialogInterface dialog,
int which) {
dialogIsDisplayed = false;
newGame(); // set up and start a new game
}
}
);
return builder.create(); // return the AlertDialog
}
};
*/
// in GUI thread, use FragmentManager to display the DialogFragment
activity.runOnUiThread(
new Runnable() {
public void run() {
final AlertDialog gameResult = builder.create();
showSystemBars();
dialogIsDisplayed = true;
gameResult.setCancelable(false); // modal dialog
// gameResult.show(activity.getFragmentManager(), "results");
gameResult.show();
}
}
);
}

Statements in "if block" are executed before function in "if condition" returns

I wrote the below code in Android. The function "confirmalert" actually displays an alert box and has positive and negative buttons.
But always the "else" part is working, that too even if I haven't selected anything.
Please reply with how to make it work properly.
private void updatestockin()
{
if(confirmalert())
{
Toast t = Toast.makeText(getApplicationContext(), "Success",
Toast.LENGTH_SHORT);
t.show();
}
else
{
Toast t = Toast.makeText(getApplicationContext(), "User Rejected", Toast.LENGTH_SHORT);
t.show();
}
}
My confirmalert function:
public boolean confirmalert(String title,String msg)
{
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setMessage(msg);
alertDialogBuilder.setTitle(title);
alertDialogBuilder.setPositiveButton("Ok",
new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface arg0, int arg1)
{
flag=true;
}
});
alertDialogBuilder.setNegativeButton("Cancel",
new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface arg0, int arg1)
{
flag=false;
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
return flag;
}
The confirmalert() method returns immediately (before the AlertDialog is even displayed on screen) with the value of the flag field which is false if not set otherwise in your class. That happens because AlertDialog.show() is asynchronous, otherwise it would block the main (ui) thread and you would not be able to interact with the app any longer after calling it.
What you need to do is move the call to confirmalert() outside of updatestockin() method and call updatestockin from the Dialog.OnClickListener().
//call this from where you normally call updatestockin()
confirmalert();
//updatestockin(); // comment this call as it will happen after the user clicks one of the AlertDialog buttons
private void updatestockin(boolean flag) {
if (flag) {
Toast t = Toast.makeText(getApplicationContext(), "Success",
Toast.LENGTH_SHORT);
t.show();
} else {
Toast t = Toast.makeText(getApplicationContext(), "User Rejected", Toast.LENGTH_SHORT);
t.show();
}
}
public boolean confirmalert(String title,String msg)
{
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setMessage(msg);
alertDialogBuilder.setTitle(title);
alertDialogBuilder.setPositiveButton("Ok",
new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface arg0, int arg1)
{
updatestockin(true);
}
});
alertDialogBuilder.setNegativeButton("Cancel",
new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface arg0, int arg1)
{
updatestockin(false);
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
return flag;
}
I think there is an async issue. So maybe this alert in different thread. So since your flag is initialized false, it runs that.
So using wait() and notify() you can sync the threads
Try this:
public boolean confirmalert(String title,String msg)
{
wait();
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setMessage(msg);
alertDialogBuilder.setTitle(title);
alertDialogBuilder.setPositiveButton("Ok",
new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface arg0, int arg1)
{
flag=true;
notify();
}
});
alertDialogBuilder.setNegativeButton("Cancel",
new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface arg0, int arg1)
{
flag=false;
notify();
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
wait();
return flag;
}
It should work. not tested. If possible read about wait and notify a bit to properly understand, hope it takes you to right path.

Differentiate single Dialogs with DialogInterface.OnClickListener

We have two AlertDialog objects
AlertDialog dialog1, dialog2;
both dialogs are created via AlertDialog.Builder.
How can we recognize which dialog is source of event in DialogInterface.OnClickListener ?
with single dialog we can do this:
AlertDialogInstance.setOnClickListener(myListener);
//myListener
public void onClick(DialogInterface arg0, int arg1) {
switch (arg1) {
case AlertDialog.BUTTON_NEGATIVE:
// do something
break;
case AlertDialog.BUTTON_POSITIVE:
// do something
break;
case AlertDialog.BUTTON_NEUTRAL:
// do something
break;
}
}
how to modify this switch logic to handle multiple dialogs?
(Or if there is better system to handle dialogs, other than inline button callbacks, what is it?)
I'll recommend you to put needed param in the custom listener.
private class CustomOnClickListener implements OnClickListener {
private int id;
public CustomOnClickListener(int id) {
this.id = id;
}
public void onClick(DialogInterface dialog, int which) {
//check id and which
}
}
Then, when you add onClickListeners to dialogs, you just provide an id to listener.
private AlertDialog dialog1;
private AlertDialog dialog1;
#Override
protected void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
dialog1 = new AlertDialog.Builder(this).setTitle("dialog1").create();
dialog1.setButton(AlertDialog.BUTTON_POSITIVE, "Yes", this);
dialog2 = new AlertDialog.Builder(this).setTitle("dialog2").create();
dialog2.setButton(AlertDialog.BUTTON_NEGATIVE, "NO", this);
}
#Override
public void onClick(final DialogInterface dialog, final int which)
{
if (dialog == dialog1)
{
if (which == AlertDialog.BUTTON_POSITIVE)
{
//
}
else if (which == AlertDialog.BUTTON_NEGATIVE)
{
//
}
}
else if (dialog == dialog2)
{
if (which == AlertDialog.BUTTON_POSITIVE)
{
//
}
else if (which == AlertDialog.BUTTON_NEGATIVE)
{
//
}
}
}
If your dialogs have differentiable content, you can obviously tell the dialog directly by its content:
if(which==AlertDialog.BUTTON_NEGATIVE)return;
AlertDialog theDialog = (AlertDialog)dialog;
if(theDialog.findViewById(R.id.phoneinput)!=null) ...;//handle the phone
if(theDialog.findViewById(R.id.emailinput)!=null) ...;//handle the email
Of course the solution is NOT universal, but quite handy in some cases.

Categories