Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

calling showAtLocation of popupwindow is crashing the app

Tags:

android

popup

I have class that extends from a View and I am trying to show a popupWindow using this code

public class dbView extends View implements View.OnTouchListener {

    private void showDialog(String msg) {
        LayoutInflater layoutInflater;
        View dialogContent;
        final PopupWindow popupWindow;

        layoutInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        dialogContent = layoutInflater.inflate(R.layout.pop_up_dialog, null);

        popupWindow = new PopupWindow(
                dialogContent,
                ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT);

        popupWindow.showAtLocation(this, Gravity.CENTER, 10, 10);

    }

}

My app is crashing when trying to execute that last line. The message of the exception is

Can't create handler inside thread that has not called Looper.prepare()

I have looked for answers related to that message and all of them involve that the popup was being created on a separate thread and that I should use runOnUIThread but If I am inside a VIEW do I need to to this ? What can be the cause of this problem ?

like image 421
Mauricio Gracia Gutierrez Avatar asked May 24 '15 14:05

Mauricio Gracia Gutierrez


3 Answers

It depends on where you are calling showDialog(String msg), i know you were calling it from your View class, but that does not mean its on the UI thread, View calls are processed on the UI thread, but if you make a View call in a Thread you will have that error. i know the same code solved itself, but if you are runing TimerTask or Threads in your View class you should double check them. And also instead of runOnUithread you can call post(runnable); (the same mechanism Handler) in your View class, that will make sure that the runnable call will be sent to the Main thread.

In short check where you calling it in your View class

like image 160
Elltz Avatar answered Oct 21 '22 15:10

Elltz


I suppose it may be caused because you're trying to interfere to your UI from non-original thread (that created the UI). Your custom view class doesn't have acess to changing the UI so I think that the best way to do that is to call runOnUIThread(). Though I have heard that using runOnUIThread may be not the best choice but it seems to me that this will be exactly what you need in your case.

Usually to get this working I make a special class that extends Application (in my case it's ContextGetter) and implement a method like this:

public class ContextGetter extends Application {

    private static Context context;

    public void onCreate(){
        super.onCreate();
        context = getApplicationContext();
    }

    public static Context getAppContext() {
        return context;
    }
}

It helps me to get the app context from everywhere. You should also add it to your manifest like this:

<application
        android:name=".ContextGetter"
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >

and include all your activities inside this tag.

When you have your context you can do this thing:

((Activity)ContextGetter.getAppContext()).runOnUiThread(new Runnable()
{
//doSomethingInside
});

It may look strange but it must work for you. It looks this way because Activity is derived from Context. Whenever you try it I'd like to know if it worked. Hope I helped with the question

like image 21
Vendetta8247 Avatar answered Oct 21 '22 16:10

Vendetta8247


in manifest

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

you can fixed it by making your own through the window manager.

private void showCustomPopupMenu()
{
            windowManager2 = (WindowManager)getSystemService(WINDOW_SERVICE);
            LayoutInflater layoutInflater=(LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            View view=layoutInflater.inflate(R.layout.xxact_copy_popupmenu, null);
            params=new WindowManager.LayoutParams(
                    WindowManager.LayoutParams.WRAP_CONTENT,
                    WindowManager.LayoutParams.WRAP_CONTENT,
                    WindowManager.LayoutParams.TYPE_PHONE,
                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                    PixelFormat.TRANSLUCENT);

            params.gravity=Gravity.CENTER|Gravity.CENTER;
            params.x=10;
            params.y=10;
            windowManager2.addView(view, params);  
}
like image 24
krunal shah Avatar answered Oct 21 '22 16:10

krunal shah