Unable to dismiss dialog in runOnUiThread - android

I'm scanning QR code using Google's Vision. I got help from this link. I want to show AlertDialog after getting the value from QR code. If I directly show alertdialog inside receiveDetections() method I'm getting "Can't create looper" error. So I called the alertdialog inside runOnUiThread(). But now I'm unable to dismiss the dialog. Would like to know what's the reason for this.
#Override
public void receiveDetections(Detector.Detections<Barcode> detections){
final SparseArray<Barcode> barcodes = detections.getDetectedItems();
if (barcodes.size() != 0) {
runOnUiThread(new Runnable() {
#Override
public void run() {
try {
String val = barcodes.valueAt(0).displayValue;
showAlert(val);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
private void showAlert(String val){
try {
if (!val.equals("")) {
AlertDialog.Builder builder = new AlertDialog.Builder(ScannedBarcodeActivity.this);
builder.setTitle(emp.getName())
.setPositiveButton(newStatus, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
emp.setStatus(newStatus);
viewModel.updateEmployee(emp);
dialog.dismiss();
}
})
.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
AlertDialog alertDialog = builder.create();
alertDialog.show();
}
}catch (Exception e){
e.printStackTrace();
}
}
Even though now the alertdialog is showing, when I click CANCEL button, the alert does not gets dismissed.

I think receiveDetections is being called more than once, which is resulting in multiple instances of AlertDialog. So when you press CANCEL button you might be cancelling only one of those multiple opened dialogs.
You can add logs to see how many times receiveDetections is being called, or just hit CANCEL button multiple times and all the previously opened alerts will be cancelled
*Possible Reason:
receiveDetections will be executed every-time your camera passes image to QRScanner,
and as your camera is continuously streaming images, QRScanner is calling receiveDetections again and again.

The reason why you alert dialog is not dismissing because you are new object of AlertDialog each time when receiveDetections called and in your case receiveDetections multiple time.
You have to create a Singleton class object:
public class singleTonDialogExample {
static TextToSpeech t1;
private static singleTonExample ourInstance = new singleTonDialogExample();
private Context appContext;
private ICallBack iCallBack;
public interface ICallBack{
void onYesPressed();
void onNoPressed();
}
private singleTonDialogExample() { }
public static Context get() {
return getInstance().getContext();
}
public static synchronized singleTonDialogExample getInstance() {
return ourInstance;
}
public void init(Context context) {
if (appContext = = null) {
this.appContext = context;
}
}
private Context getContext() {
return appContext;
}
public void setICallBack(ICallBack callBack){
this.iCallBack=callBack;
}
public void AlertDialog(final MainActivity mainActivity,String title,String message) {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(mainActivity);
alertDialogBuilder.setMessage(message);
alertDialogBuilder.setPositiveButton("yes",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface arg0, int arg1) {
iCallBack.onYesPressed();
}
});
alertDialogBuilder.setNegativeButton("No", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
iCallBack.onNoPressed();
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
}
Create the Dialog in Activity like this:
singleTonDialogExample dialog;
dialog = singleTonExample.getInstance();
dialog.init(getApplicationContext());
dialog.setICallBack(this);
dialog.AlertDialog(MainActivity.this,"Title","This is message");
Also implement the ICallBack interface in your activity or fragment.

Related

Activity objects persisting in memory even after calling finish and making the references null

I am making a retrofit enqueue call from SplashActivity and passing data to next activity via bundles.Even after explicitly calling finish on splash activity it still has 48 references in retained heap as seen in MAT.
The app in general is also taking a lot of memory in the background. I debugged and found that my activity's onDestroy() method is getting called, but why are the objects still persistent in the memory? Is it somehow related to the data being passed by reference instead of value? I've been trying to search around the web but with hardly any luck. Please point me if I'm looking in the wrong direction here.
Here's a snapshot of my Splash Activity-
public class SplashActivity extends AppCompatActivity {
private String TAG = SplashActivity.class.getSimpleName();
List<Sport> mSportsList;
List<Event> mEventsList;
List<Carousel> mCarouselList;
WatchOnApiService mWatchOnApiService;
#BindString(R.string.package_name)
String mPackageName;
ProgressBar mProgressBar;
AlertDialog.Builder alertDialogBuilder;
AlertDialog alertDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
ButterKnife.bind(this);
MobileAds.initialize(getApplicationContext(), "ca-app-pub-8433136449848959~7585529227");
mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
mProgressBar.getIndeterminateDrawable().setColorFilter(Color.WHITE, PorterDuff.Mode.MULTIPLY);
}
#Override
protected void onResume() {
super.onResume();
getSportsAndEventsAndCarousel();
}
private void getSportsAndEventsAndCarousel() {
mProgressBar.setVisibility(View.VISIBLE);
WatchOnApiService mWatchOnApiService = RetrofitFactory.getRetrofit().create(WatchOnApiService.class);
final Call<WatchOnSportsEventsCarousel> mCall = mWatchOnApiService.getAllSportsAndEventsAndCarousel(TimeZone.getDefault().getID());
mCall.enqueue(new Callback<WatchOnSportsEventsCarousel>() {
#Override
public void onResponse(final Response<WatchOnSportsEventsCarousel> response, Retrofit retrofit)
{
if (response.isSuccess()) {
mProgressBar.setVisibility(View.INVISIBLE);
if (Float.parseFloat(BuildConfig.VERSION_NAME) < Float.parseFloat(response.body().getAndroidLatestVersion())) {
if (response.body().getAndroidForceUpdate().equalsIgnoreCase("1")) {
showForceUpdateDialog();
} else {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(SplashActivity.this);
alertDialogBuilder.setTitle("WatchOn");
alertDialogBuilder.setMessage("WatchOn just got better.Would you like to upgrade ?");
alertDialogBuilder.setPositiveButton("Upgrade",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int arg1) {
dialog.dismiss();
try { SplashActivity.this.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + mPackageName)));
} catch (android.content.ActivityNotFoundException anfe) {
SplashActivity.this.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + mPackageName)));
}
}
});
alertDialogBuilder.setNegativeButton("Dismiss", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
beginFlow(response);
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
} else {
beginFlow(response);
}
}
//Response not received something went wrong
else {
showAlertDialogNoResponse();
}
}
private void beginFlow(final Response<WatchOnSportsEventsCarousel> response) {
Bundle mBundle = new Bundle();
mSportsList = CodeUtils.convertSportsListToLocalTime(response.body().getData().getSports());
Parcelable wrappedSports = Parcels.wrap(new ArrayList<>(mSportsList));
mBundle.putParcelable(AppConstants.SPORTS_LIST, wrappedSports);
mEventsList = CodeUtils.convertEventsListToLocalTime(response.body().getData().getEvents());
Parcelable wrappedEvents = Parcels.wrap(new ArrayList<>(mEventsList));
mBundle.putParcelable(AppConstants.EVENTS_LIST, wrappedEvents);
mCarouselList = response.body().getData().getCarousels();
Parcelable wrappedCarousels = Parcels.wrap(new ArrayList<>(mCarouselList));
mBundle.putParcelable(AppConstants.CAROUSELS_LIST, wrappedCarousels);
if ((response.body().getLiveSponsors() == 1)) {
mBundle.putBoolean(AppConstants.LIVE_SPONSORS_AVAILABLE, true);
} else {
mBundle.putBoolean(AppConstants.LIVE_SPONSORS_AVAILABLE, false);
}
Intent i = new Intent(SplashActivity.this, SelectSportEventActivity.class);
i.putExtras(mBundle);
mSportsList = null;
mEventsList = null;
mCarouselList = null;
startActivity(i);
SplashActivity.this.finish();
}
#Override
public void onFailure(Throwable t) {
showAlertDialogInternetFail();
alertDialogBuilder.setNegativeButton("Retry", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
getSportsAndEventsAndCarousel();
dialog.dismiss();
}
});
alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
});
}
#Override
protected void onDestroy() {
ButterKnife.unbind(this);
Log.d(TAG, "onDestroy: " + mSportsList + mEventsList + mCarouselList);
alertDialog = null;
super.onDestroy();
}
}

How to convert this inner AsyncTask in outer one?

I created this AsyncTask inner class and now I want to make it outer. Here is the code:
private class DownloadDataFromServer extends AsyncTask<String, Integer, String> {
ProgressDialog dialog;
boolean connErr = false;
boolean soErr = false;
#Override
protected void onPreExecute() {
dialog = new ProgressDialog(HomePage.this); !!!!PROBLEM!!!!
dialog.setIndeterminate(false);
dialog.setMax(100);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setCancelable(false);
dialog.setTitle("Download");
dialog.setMessage("Updating...");
dialog.show();
super.onPreExecute();
}
#Override
protected String doInBackground(String... urls) {
// do something
}
protected void onProgressUpdate(Integer... progress) {
// Update the progress
dialog.setProgress(progress[0]);
}
#Override
protected void onPostExecute(String result) {
if (connErr || soErr) {
String msg = "Bad connection";
AlertDialog.Builder builder;
builder = new AlertDialog.Builder(HomePage.this); !!!!PROBLEM!!!!
builder.setCancelable(false);
builder.setTitle("Connection timeout");
builder.setMessage(msg);
builder.setPositiveButton("Retry", new DialogInterface.OnClickListener(){
#Override
public void onClick(DialogInterface dialog, int which)
{
dialog.dismiss();
new DownloadDataFromServer().execute(new String[] { "http://www.example.com" });
}
});
builder.setNegativeButton("Exit", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
finish(); !!!!PROBLEM!!!!
}
});
AlertDialog dialog = builder.create();
dialog.show();
} else {
if (Integer.parseInt(result) <= 0) {
Toast.makeText(getBaseContext(), "Error!", Toast.LENGTH_SHORT).show(); !!!!PROBLEM!!!!
} else {
Toast.makeText(getBaseContext(), "OK!", Toast.LENGTH_SHORT).show(); !!!!PROBLEM!!!!
}
}
dialog.dismiss();
}
}
Please note "!!!!PROBLEM!!!!" strings in the above code: there are all the errors that I get. I tried to apply some workarounds but finally I could not make it working. In addition I also have to use
private Database db = new Database(this);
but I do not know what to put in place of "this". Please help me to convert this inner class in the right way.
You should make one argument constructor to DownloadDataFromServer class and pass Context as argument like
Context mCon;
public DownloadDataFromServer(Context con){
this.mCon=con;
}
and used this mCon context to anywhere in your DownloadDataFromServer like so
builder = new AlertDialog.Builder(mCon);
and at last called DownloadDataFromServer from any Activity like
new DownloadDataFromServer(your_Activity.this).execute(......);
Make yout DownloadDataFromServer have a constructor accepting HomeScreen, save the home screen in a field in the constructor and then use that field everywhere instead of HomeScreen.this.
You may have to make some of your private fields of HomeScreen public (or provide accessors) because of that.
You do not want to do all that though, what's the advantage?

Android testing that an alertDialog is shown in an activity

Hello and thank you for taking the time to read this question.
I am trying to write an instrumentation test for an activity. The scenario is the following:
If on create of the activity the GPS is not enabled, an alertDialog should be shown to the user to suggest turning on the sensor. The check is performed by an utility class that checks the connectivity and shows the alertDialog if necessary. I want to be able to test in my class if the dialog is shown to the user.
Now for some code:
The activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
...
Utils.checkGPSProvider(this);
}
The Utility class:
public final class Utils {
private Utils() {
}
private static void createAlertDialog(final Context context, final String message, final String intentAction) {
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
final Intent callSettingIntent = new Intent(intentAction);
alertDialogBuilder.setMessage(message).setPositiveButton(POSITIVE_BUTTON,
new DialogInterface.OnClickListener() {
#Override
public void onClick(final DialogInterface dialog, final int id) {
context.startActivity(callSettingIntent);
}
});
alertDialogBuilder.setNegativeButton(NEGATIVE_BUTTON, new DialogInterface.OnClickListener() {
#Override
public void onClick(final DialogInterface dialog, final int id) {
dialog.cancel();
}
});
final AlertDialog alert = alertDialogBuilder.create();
alert.show();
}
public static void checkGPSProvider(final Context context) {
String message;
message = "GPS message";
final LocationManager mlocManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
if (!mlocManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
createAlertDialog(context, message, android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
}
}
}
The test class:
public class UtilsTest extends ActivityInstrumentationTestCase2<MyActivity> {
private MyActivity activity;
#Mock
LocationManager mlocManager;
public UtilsTest() {
super(MyActivity.class);
}
public UtilsTest(Class<MyActivity> activityClass) {
super(activityClass);
}
#Override
public void setUp() throws Exception {
super.setUp();
activity = getActivity();
MockitoAnnotations.initMocks(this);
}
public void testWhenGPSIsDisabled_ShouldShowAlertDialog() {
when(mlocManager.isProviderEnabled(LocationManager.GPS_PROVIDER)).thenReturn(false);
if (mlocManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
Assert.fail("GPS should be disabled");
}
(insert code here that should test that the alertDialog is shown)
}
}
I know that the Dialog class has an isShown() method but I do not know how to get the dialog reference to test the isShown method.
If there is any other necessary information I will try to provide it to you.
Thank you.
You can return the reference of the AlertDialog from the method createAlertDialog
example:
private static AlertDialog createAlertDialog(final Context context, final String message, final String intentAction)
When you call this method you can then get the return reference value of the method same as your checkGPSProvider should also return AlertDialog.
sample:
public static AlertDialog checkGPSProvider(final Context context) {
String message;
message = "GPS message";
final LocationManager mlocManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
if (!mlocManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
return createAlertDialog(context, message, android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
}
}
And in your oncreate method of the activity create a Field for AlertDialog and instantiate with the Utils.checkGPSProvider(this);
solution:
your_alert_dialog = Utils.checkGPSProvider(this);

Access a database from a DialogFragment and toast a message

I have a DialogFragment which displays a simple yes/no question.
When the user presses "yes", I perform a database request (which basicaly deletes an entry).
I then toast a message to report a success or failure to the user.
I try to avoid calling the database from the UI thread, so I created a thread which will delete the entry, and from that thread I call a handler in the DialogFragment to display the toast message.
My problem is that when the user presses the button, the thread is started and the dialog is closed. As the thread is started, the data is deleted from the database. But when I toast my message from the handler, the DialogFragment is already detached from the parent Activity so I don't have a context anymore to call Toast.makeText().
My question is how can I toast the message ?
I know I could create a Service to handle the database operation, but wouldn't it be too much hassle ?
Is there a simpler way ?
Thanks !
EDIT : here is my code, to help you understand my problem :
public class EraseHistoryDialogFragment extends DialogFragment {
private HistoryDatabaseHandler mHistoryDbHandler;
private final static int MSG_NOTIFY_EMPTYDB = 1;
private final static int MSG_NOTIFY_DELENTRY = 2;
private final static int MSG_NOTIFY_NODELETION = 3;
private Context mContext;
private Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_NOTIFY_DELENTRY:
Toast.makeText(mContext,
getS tring(R.string.historytab_erased_entry),
Toast.LENGTH_SHORT).show();
break;
case MSG_NOTIFY_EMPTYDB:
Toast.makeText(mContext,
getS tring(R.string.historytab_history_cleared),
Toast.LENGTH_SHORT).show();
break;
case MSG_NOTIFY_NODELETION:
Toast.makeText(mContext,
getS tring(R.string.historytab_erase_failed),
Toast.LENGTH_SHORT).show();
break;
}
};
};
private Runnable mEraseHistoryRunnable = new Runnable() {
#Override
public void run() {
if (mHistoryDbHandler.clearAllTables()) {
mHandler.sendEmptyMessage(MSG_NOTIFY_EMPTYDB);
} else {
mHandler.sendEmptyMessage(MSG_NOTIFY_NODELETION);
}
}
};
private class EraseEntryRunnable implements Runnable {
private String mEntryId;
public EraseEntryRunnable(String entryID) {
mEntryId = entryID;
}
#Override
public void run() {
if (mHistoryDbHandler.deleteEntry(mEntryId)) {
mHandler.sendEmptyMessage(MSG_NOTIFY_DELENTRY);
} else {
mHandler.sendEmptyMessage(MSG_NOTIFY_NODELETION);
}
}
};
public static EraseHistoryDialogFragment newInstance(String message,
String entryID, boolean eraseAll) {
EraseHistoryDialogFragment frag = new EraseHistoryDialogFragment();
Bundle args = new Bundle();
args.putString("message", message);
args.putString("entryid", entryID);
args.putBoolean("eraseall", eraseAll);
frag.setArguments(args);
return frag;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
mHistoryDbHandler = HistoryDatabaseHandler.getInstance(getActivity());
mContext = getActivity().getApplicationContext();
String message = getArguments().getString("message");
final String entryID = getArguments().getString("entryid");
final boolean eraseAll = getArguments().getBoolean("eraseall");
return new AlertDialog.Builder(getActivity())
.setMessage(message)
.setPositiveButton(R.string.groupstab_yes,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
if (eraseAll) {
Thread emptyDbT = new Thread(
mEraseHistoryRunnable);
emptyDbT.start();
} else {
Thread deleteEntryT = new Thread(
new EraseEntryRunnable(entryID));
deleteEntryT.start();
}
}
})
.setNegativeButton(R.string.groupstab_no,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
getDialog().dismiss();
}
}).create();
}
}
try with getActivity(); instead of getApplicationContext();
like this
Toast.makeText(getActivity(), "Your Message", Toast.LENGTH_SHORT).show();
Try getActivity().getApplicationContext() to get the ApplicationContext

Show dialog alert from a non-activity class in android

I want to show an Alert Dialog via AlertDialogManager class to a non-activity class DeviceAdminReceiverSample's method onDisabled, but whenever I call alertDialog via that method it generates error with following text
Error
06-12 12:01:19.923: E/AndroidRuntime(468): FATAL EXCEPTION: main
06-12 12:01:19.923: E/AndroidRuntime(468): java.lang.RuntimeException: Unable to start
receiver com.android.remotewipedata.DeviceAdminReceiverSample:
android.view.WindowManager$BadTokenException: Unable to add window -- token null is not
for an application
I know the issue is with context thing but I don't know what to put there so that it work, I tried this, getApplicationContext() but all vain. My code for both classes is below
AlertDialogManager
public class AlertDialogManager {
public void showAlertDialog(Context context, String title, String message,
Boolean status) {
final AlertDialog alertDialog = new AlertDialog.Builder(context).create();
alertDialog.setTitle(title);
alertDialog.setMessage(message);
if (status != null)
alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
alertDialog.dismiss();
}
});
alertDialog.show();
}
}
DeviceAdminReceiverSample
public class DeviceAdminReceiverSample extends DeviceAdminReceiver {
static final String TAG = "DeviceAdminReceiver";
AlertDialogManager alert = new AlertDialogManager();
/** Called when this application is no longer the device administrator. */
#Override
public void onDisabled(Context context, Intent intent) {
super.onDisabled(context, intent);
Toast.makeText(context, R.string.device_admin_disabled,
Toast.LENGTH_LONG).show();
// intent.putExtra("dialogMessage", "Device admin has been disabled");
// intent.setClass(context, DialogActivity.class);
// intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// context.startActivity(intent);
alert.showAlertDialog(context, "Alert",
"Device admin has been disabled", true);
}
Just add this before your alertDialog.show();
alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
or try following if above didn't work:
alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_PANEL);
and use this permission:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
The problem is 'You can show AlertDialogs from Activity only'. This is not an issue of context.
Although this is not a good idea to show dialog from receiver (better is to use Notification), But if you want to do so you can create an Activity as dialog and show
If you always want to get the current activity from anywhere in the app you can register an ActivityLifecycleCallback on your Application instance.
Here's an untested implementation that might get you closer.
public class TestApp extends Application {
private WeakReference<Activity> mActivity = null;
#Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
mActivity = new WeakReference<Activity>(activity);
}
#Override
public void onActivityDestroyed(Activity activity) {
mActivity.clear();
}
/** Unused implementation **/
#Override
public void onActivityStarted(Activity activity) {}
#Override
public void onActivityResumed(Activity activity) {}
#Override
public void onActivityPaused(Activity activity) {}
#Override
public void onActivityStopped(Activity activity) {}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}
});
}
public Activity getCurrentActivity() {
return mActivity.get();
}
}
Then to use this throughout your app you would do some call like this ...
Activity activity = ((TestApp)getApplicationContext()).getCurrentActivity();
The advantages are you can always keep track of your current activity, however its a little too overkill for just handling Dialogs from within the Activity.
call this method in activity class
public static void showAlert(Activity activity, String message) {
TextView title = new TextView(activity);
title.setText("Title");
title.setPadding(10, 10, 10, 10);
title.setGravity(Gravity.CENTER);
title.setTextColor(Color.WHITE);
title.setTextSize(20);
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
// builder.setTitle("Title");
builder.setCustomTitle(title);
// builder.setIcon(R.drawable.alert_36);
builder.setMessage(message);
builder.setCancelable(false);
builder.setNegativeButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
}
Here's what I made and use:
myDialog.java:
import android.app.Activity;
import android.content.DialogInterface;
import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
public class myDialog {
private Activity mActivity;
myDialog(Activity a) {
this.mActivity = a;
}
#SuppressWarnings("InflateParams")
public void build(String title, String msg) {
LayoutInflater inflater = LayoutInflater.from(mActivity);
View subView = inflater.inflate(R.layout.dialog_box_text, null);
final TextView message = subView.findViewById(R.id.message);
message.setText(msg);
AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
builder.setTitle(title);
builder.setView(subView);
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
AlertDialog alert = builder.create();
alert.show();
}
}
dialog_box_text.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="1"
android:orientation="horizontal">
<TextView
android:id="#+id/message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=" "
android:maxLines="1"
android:textColor="#color/colorBlack" />
</LinearLayout>
Example code:
public class MainActivity extends AppCompatActivity {
private myDialog md;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
md = new myDialog(this);
...
md.build("Title", "Message");
You can define a public Context var in the MainActivity with initial value (this); As show here:
public class MainActivity< alertdail > extends AppCompatActivity {
////////////////////////////////////////////////////////////
//Public var refers to Main Activity:
Context mainActivity = this;
////////////////////////////////////////////////////////////
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate ( savedInstanceState );
setContentView ( R.layout.activity_main );
AlertDialogManager alert =new AlertDialogManager ();
alert.showAlertDialog ( this,"Title","Message",true );
}
public class AlertDialogManager {
public void showAlertDialog(Context context, String title, String message,
Boolean status) {
final AlertDialog alertDialog = new AlertDialog.Builder ( mainActivity ).create ( );
alertDialog.setTitle ( title );
alertDialog.setMessage ( message );
if (status != null)
alertDialog.setButton ( "OK", new DialogInterface.OnClickListener ( ) {
public void onClick(DialogInterface dialog, int which) {
alertDialog.dismiss ( );
}
} );
alertDialog.show ( );
}
public void showAlertDialog(Context c) {
}
}
public class DeviceAdminReceiverSample extends DeviceAdminReceiver {
static final String TAG = "DeviceAdminReceiver";
AlertDialogManager alert = new AlertDialogManager ( );
/**
* Called when this application is no longer the device administrator.
*/
#Override
public void onDisabled(Context context, Intent intent) {
super.onDisabled ( context, intent );
Toast.makeText ( context, R.string.device_admin_disabled,
Toast.LENGTH_LONG ).show ( );
// intent.putExtra("dialogMessage", "Device admin has been disabled");
// intent.setClass(context, DialogActivity.class);
// intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// context.startActivity(intent);
alert.showAlertDialog ( context, "Alert",
"Device admin has been disabled", true );
}
}
}
Here's a quick method of properly performing this task that has done the job for me. Basically, what you would do is just create a new thread.
Declare a public and static variable with a type that matches the original activity class.
public static Activity1 activity;
Activity1 is the class that the variable resides in.
Upon calling the method onCreate();, set the variable to be equal to the context of the activity, otherwise known as this.
Example:
#Override
protected void onCreate( Bundle savedInstanceState ) {
super.onCreate( savedInstanceState );
activity = this;
}
3. Since we now have the context of the activity, we can use it to create a function with an alert dialog by using the runOnUiThread(); method inside of the function that will call the alert dialog. We would use a new Runnable() for the runnable action required for runOnUiThread();, and to have the alert dialog actually open, we would override the run function of a runnable item and place the code for the alert dialog in there.
Example function:
public static void exampleDialog(){
Activity1.activity.runOnUiThread(new Runnable){
#Override
public void run(){
//alert dialog code goes here. For the context, use the activity variable from Activity1.
}
}
}
Hope this helps :)

Categories

Resources