onBackPressed not called when PopupWindow is showing - android

Hee guys,
So currently I'm using a PopupWindow to display an in app browser. However when pressing the back button it does nothing. I'm using the PopupWindow in another Fragment, then I use a statement to set the PopupWindow in my FragmentActivity and then when I press my back button it should check if the PopupWindow is set or not and dismiss it or not. However it doesn't even run through the onBackPressed.
PopupWindow in fragment:
--> is where I point out the line which makes sure the FragmentActivity gets the PopupWindow as well.
// Use webview for icons and website link.
public void inAppBrowser(String url){
mCursor.moveToFirst();
// Inflate View
LayoutInflater layoutInflater = (LayoutInflater) ((MainActivity) MainActivity.getContext()).getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View inflatedView = layoutInflater.inflate(R.layout.browser_window, null, false);
// Control View Childs.
LinearLayout header = (LinearLayout) inflatedView.findViewById(R.id.filter_header);
header.setBackgroundColor(Color.parseColor(color));
Button cancel = (Button) inflatedView.findViewById(R.id.cancel);
Button done = (Button) inflatedView.findViewById(R.id.done);
// Set PopupWindow position.
Display display = ((MainActivity) MainActivity.getContext()).getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
// Control PopupWindow.
final PopupWindow popWindow = new PopupWindow(inflatedView, size.x, size.y, true);
popWindow.setAnimationStyle(android.R.anim.fade_in);
popWindow.setFocusable(true);
popWindow.setOutsideTouchable(true);
popWindow.showAtLocation(v, Gravity.BOTTOM, 0, 150);
--> MainActivity.setPopupWindow(popWindow);
// Control WebView
WebView myWebView = (WebView) inflatedView.findViewById(R.id.webview);
myWebView.setWebViewClient(new WebViewClientAdapter());
myWebView.clearCache(true);
myWebView.clearHistory();
myWebView.getSettings().setJavaScriptEnabled(true);
myWebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
MainActivity.setWebView(myWebView);
if (url != null) {
if (url.contains("http://") || url.contains("https://")) {
} else {
url = "http://" + url;
}
myWebView.loadUrl(url);
} else {
popWindow.dismiss();
MainActivity.setPopupWindow(null);
MainActivity.setWebView(null);
}
cancel.setVisibility(View.INVISIBLE);
done.setText("Close");
done.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
popWindow.dismiss();
}
});
}
My onBackPressed code :
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
//check if popupwindow is open
Log.e(TAG, "Check if it runs through this section");
if (popWindow != null) {
if (myWebView != null && myWebView.canGoBack()) {
myWebView.goBack();
} else {
popWindow.dismiss();
popWindow = null;
myWebView = null;
}
}
}
Ignore the WebView for now. That might be a question in the future, but I want the PopupWindow to close first. Any help is appreciated.

Make your PopupWindow not focusable:
final PopupWindow popWindow = new PopupWindow(inflatedView, size.x, size.y, false);
Also remove this line which was redundant:
popWindow.setFocusable(true);

I think you should define a static method removePopupWindow(view v) in MainActivity,
and call it inside onBackPressed() like MainActivity.removePopupWindow(popWindow);
Hope It will help you.

Ok, so this question was asked a long time ago, but I think I have a better solution. What I've done is add an OnDismissListener to my popup. In this listener I've added the code I wanted to execute when the popup got dismissed. This way Android still get's to manage the opening and closing of the popup and I just added a single line to make it work.
This is the way to add one:
yourAwesomePopupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
#Override
public void onDismiss() {
// Your code on dismiss here
}
});

popup.showAtLocation(popupView, Gravity.CENTER,0,0);
popupshowing=true;// define this as a global
#Override
public void onBackPressed() {
if(popupshowing) {
popup.dismiss();
popupshowing=false;
}
else {
super.onBackPressed();
}
}

You can use this.
Dialog dialog = new Dialog(ActivityMain.this);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_TOAST); dialog.setContentView(R.layout.mydialog);
dialog.setCancelable(true);
dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
try {
if (mScannerView!=null) {
mScannerView.stopCamera();
}
} catch(Exception e){
e.printStackTrace();
}
}
});

Related

Issue about the return value of activityStarting

Today I'm developing an App which can intercept the launch between activities, My key code is:
ActivityManagerNative.getDefault().setActivityController(new InterceptActivityController(), false);
private class InterceptActivityController extends IWeChatActivityController.Stub {
void InterceptActivityController() {}
#Override
public boolean activityStarting(Intent intent, String pkg) {
showDialog();
return false;
}
}
private void showBottomDialog() {
Log.d(TAG, "showBottomDialog");
Dialog bottomDialog = new Dialog(mContext);
View contentView = LayoutInflater.from(this).inflate(android.R.layout.simple_list_item_2, null);
bottomDialog.setContentView(contentView);
ViewGroup.LayoutParams layoutParams = contentView.getLayoutParams();
layoutParams.width = getResources().getDisplayMetrics().widthPixels;
contentView.setLayoutParams(layoutParams);
bottomDialog.getWindow().setGravity(Gravity.BOTTOM);
bottomDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
bottomDialog.show();
}
I defined a Button and planned to start an Activity after clicking it. But now I intercept this action and just show a dialog in the function of activityStarting and then return false, after dismissing this dialog, I click the button again, but nothing works, dialog doesn't show any more, Who knows the reason ? Maybe I think this is a google source bug, but I'm not sure.
You know the Dialogs need to be Shown in a Timely manner. I mean You need the Dialog to be Shown for How Long? When you Start showing a Dialog and Dismiss it, It's Not Destroyed, It's just Dismissed.
Look at the Code below. I wrote this in my own app, It's Safe. Try it and see if you're satisfied with it:
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
bottomDialog.show();
new Thread(new Runnable() {
#Override
public void run() {
try {
for (int i = 0; i <= 1200; i++) {
Thread.sleep(100); //The time it takes to update i
if (i = 1200) {
bottomDialog.dismiss();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
You can use AsyncTask as well. Also, I put the whole thing in a Click Listener just to show how it can be used.
The idea is define a showing Time for the Dialog

PopupWindow - not working on a few devices

I use following code to show a small popup:
public static PopupWindow showImportMenu(Activity activity, View anchor, PopupWindowClickListener onClickListener)
{
LayoutInflater inflater = LayoutInflater.from(activity);
PopupImportBinding binding = DataBindingUtil.inflate(inflater, R.layout.popup_import, null, false);
if (!RootTools.isRootAvailable())
binding.llImportRootMethod.setVisibility(View.GONE);
PopupWindow popupWindow = new PopupWindow(activity, null, R.attr.popupMenuStyle);
popupWindow.setFocusable(true);
popupWindow.setContentView(binding.getRoot());
popupWindow.setOutsideTouchable(true);
PopupWindowCompat.showAsDropDown(popupWindow, anchor, 0, 0, Gravity.BOTTOM);
View.OnClickListener clickListener = new View.OnClickListener()
{
#Override
public void onClick(View view)
{
onClickListener.onClick(popupWindow, view);
}
};
binding.llImportDefault.setOnClickListener(clickListener);
binding.llImportRootMethod.setOnClickListener(clickListener);
binding.llImportHTCFromContacts.setOnClickListener(clickListener);
binding.llImportManual.setOnClickListener(clickListener);
return popupWindow;
}
This works on a lot of devices but on some rare devices it does not work, like:
Android 5.1.1 root slim rom
maybe others... until now, I don't know more about other devices
I got the feedback that no popup is shown. Does anyone know why this is not working on the above mentioned device? And what I can do to make it work on this device as well?
EDIT
It seems like it's not clear that what I want is following:
use showAsDropDown not showAtLocation or similar, I never saw this problem with showAtLocation yet
my solution is working on nearly all devices, it seems to be a phone/rom specific problem, maybe it's not even solvable as it COULD be a bug in the device as well => if someone knows of such a bug, telling me would be fine as well
I don't want to use a dialog (or anything else) instead, that's not answering my question. I currently use a BottomSheet which is fine for me, but still I would like to know if the problem can be solved and somehow handled
I got the same problem on a Nexus 7 (not 2012) running the 5.1.1. It is finally fixed by adding this line:
popupWindow.setWindowLayoutMode(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
I was having the same problem: my PopupWindow was not showing on my 5.1.1 android device but it was on others. I realised that I had to specify the width and height in order to be shown on that version (which is still compatible with the rest of the versions as well).
Here is an example:
popUp.setWidth(MATCH_PARENT);
popUp.setHeight(WRAP_CONTENT);
In my case, popup window have no sizes on few devices.
Try that after setContentView
50000 - just a big size for measure.
popupWindow.getContentView().measure(50000, 50000);
popupWindow.setWidth(popupWindow.getContentView().getMeasuredWidth());
popupWindow.setHeight(popupWindow.getContentView().getMeasuredHeight());
You can use screen size instead 50000
Some ROMs restrict usage of popupview with their own permissions. So user have to explicitly turn on permission to show pop up views.
Even MIUI will restrict popupview to be displayed by default.
Please have a look whether there is any permission in that ROMs or devices.
Try QuickAction
Activity (ExampleActivity1.java) to show how to use QuickAction:
public class Example1Activity extends Activity {
private static final int ID_ADD = 1;
private static final int ID_ACCEPT = 2;
private static final int ID_UPLOAD = 3;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.example1);
ActionItem addItem = new ActionItem(ID_ADD, "Add", getResources().getDrawable(R.drawable.ic_add));
ActionItem acceptItem = new ActionItem(ID_ACCEPT, "Accept", getResources().getDrawable(R.drawable.ic_accept));
ActionItem uploadItem = new ActionItem(ID_UPLOAD, "Upload", getResources().getDrawable(R.drawable.ic_up));
//use setSticky(true) to disable QuickAction dialog being dismissed after an item is clicked
uploadItem.setSticky(true);
final QuickAction mQuickAction = new QuickAction(this);
mQuickAction.addActionItem(addItem);
mQuickAction.addActionItem(acceptItem);
mQuickAction.addActionItem(uploadItem);
//setup the action item click listener
mQuickAction.setOnActionItemClickListener(new QuickAction.OnActionItemClickListener() {
#Override
public void onItemClick(QuickAction quickAction, int pos, int actionId) {
ActionItem actionItem = quickAction.getActionItem(pos);
if (actionId == ID_ADD) {
Toast.makeText(getApplicationContext(), "Add item selected", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(), actionItem.getTitle() + " selected", Toast.LENGTH_SHORT).show();
}
}
});
mQuickAction.setOnDismissListener(new QuickAction.OnDismissListener() {
#Override
public void onDismiss() {
Toast.makeText(getApplicationContext(), "Ups..dismissed", Toast.LENGTH_SHORT).show();
}
});
Button btn1 = (Button) this.findViewById(R.id.btn1);
btn1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mQuickAction.show(v);
}
})
Button btn2 = (Button) this.findViewById(R.id.btn2);
btn2.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mQuickAction.show(v);
mQuickAction.setAnimStyle(QuickAction.ANIM_GROW_FROM_CENTER);
}
});
}
}
Output:
(source: unitid.nl)
## Ok i implemented popupwindow for sorting in my tab fragment and i checked working fine once try this
I used in that custom layout for popup window
final PopupWindow popupWindow = new PopupWindow(getActivity());
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.popmenu1t1, null);
l8[![enter image description here][1]][1] = (LinearLayout) view.findViewById(R.id.atoz);
l8.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
date_sort="0";
discount_sort="";
price_sort="";
alpha_sort="";
popupWindow.dismiss();
}
});
int width = 900;
int height = 400;
try {
WindowManager wm = (WindowManager)view.getContext().getSystemService(Context.WINDOW_SERVICE);
width = wm.getDefaultDisplay().getWidth();
height = wm.getDefaultDisplay().getHeight();
} catch (Exception e) {
e.printStackTrace();
}
popupWindow.setWidth(width*3/6);
popupWindow.setFocusable(true);
popupWindow.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
popupWindow.setContentView(view);
popupWindow.setBackgroundDrawable(null);
popupWindow.setOutsideTouchable(true);
popupWindow.showAtLocation(view, Gravity.CENTER, 0, 0);
Find the below attached screen shot popupwindow in my app
I had created a custom popup dialog shows at bottom of screen
public class MoreOptionDialog {
private Dialog dialog;
private Context context;
private int size;
public MoreOptionDialog(Context context) {
this.context = context;
}
public void showMoreOptionDialog(List<String> listMoreOption) {
dialog = new Dialog(new ContextThemeWrapper(context, R.style.DialogSlideAnim));
dialog.getWindow().setWindowAnimations(R.style.DialogSlideAnim);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
View view = View.inflate(context, R.layout.dialog_more_option, null);
dialog.setContentView(view, new LinearLayout.LayoutParams(utility.getScreenWidth() - 100, size));
dialog.getWindow().setGravity(Gravity.BOTTOM);
ListView listView = (ListView) view.findViewById(R.id.lvMoreOption);
MoreOptionAdapter moreOptionAdapter = new MoreOptionAdapter(context, listMoreOption, Gravity.CENTER);
listView.setAdapter(moreOptionAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
dialog.dismiss();
}
});
dialog.show();
}
}
And style is here
<style name="DialogSlideAnim">
<item name="android:windowAnimationStyle">#style/DialogAnimation</item>
<item name="android:windowBackground">#color/color_white</item>
<item name="android:windowFrame">#null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowActionBar">false</item>
</style>
And this dialog working in all devices :)

Return a value from Popup Window

I have popup window class like the following.
public class Popup extends PopupWindow {
Context context;
EditText et_bankname, et_banknumber;
String bank_name, account_number;
public Popup(Context ctx) {
super(ctx);
context = ctx;
setContentView(LayoutInflater.from(context).inflate(R.layout.bank_details, null));
setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
View popupView = getContentView();
setFocusable(true);
Button btn_close = (Button) popupView.findViewById(R.id.popupClose);
Button btn_submit = (Button) popupView.findViewById(R.id.popupSave);
et_bankname = (EditText) popupView.findViewById(R.id.bank_name);
et_banknumber = (EditText) popupView.findViewById(R.id.bankacc_no);
btn_submit.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
bank_name = et_bankname.getText().toString();
account_number = et_banknumber.getText().toString();
if (!bank_name.equals("") && !account_number.equals("")) {
Toast t1 = Toast.makeText(context,bank_name + " "+account_number , Toast.LENGTH_SHORT);
t1.setGravity(Gravity.TOP, 0, 100);
t1.show();
dismiss();
} else {
Toast t1 = Toast.makeText(context,
"Please provide valid details", Toast.LENGTH_SHORT);
t1.setGravity(Gravity.TOP, 0, 100);
t1.show();
}
}
});
}
public void show(View v) {
showAtLocation(v, Gravity.CENTER, 0, 0);
}
}
I will access this popup in my activity by
Popup popup = new Popup(getBaseContext());
popup.show(arg1);
This works perfectly. But I want to know when this popup window gets dismissed. for this purpose now I am using Thread concept like following.
if (isPopupShowing) {
Thread thread = new Thread() {
#Override
public void run() {
while (isPopupShowing) {
if (!popup.isShowing()) {
isPopupShowing = false;
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
loadDSP(type);
}
});
}
}
}
};
thread.start();
}
But this thread will run continuesly until the popup window gets dismissed. So I feel it is better to replace this solution by any other way.
What I want?
Just intimate to my activity like "popup is closed" when popup is dismissed.
Why I am use this way?
I will use this popup window in three activty. That is why I am create a separate class for popup window.
Any help will be highly appriciated.
Thank you.
PopupWindow already has its own dismiss listener, just use it as follows
Popup popup = new Popup(getBaseContext());
popup.show(arg1);
Change that to
Popup popup = new Popup(getBaseContext());
popup.setOnDismissListener(new PopupWindow.OnDismissListener() {
#Override
public void onDismiss() {
// Do your action
}
});
popup.show(arg1);
EDIT
I hadn't noticed you were extending a PopupWindow, which already has this implemented as shown in #Jayabal's answer. Anyway this is how you would do it if the PopupWindow didn't already have it's own onDismissListener.
Simply create your own OnDismissListener Interface.
public interface onDismissListener{
public void onDismiss();
}
Add a reference to a Listener in the PopUp class and a setter.
OnDismissListener listener;
public void setOnDismissListener(OnDismissListener listener){
this.listener = listener;
}
Then in your Activity
Popup popup = new Popup(getBaseContext());
popup.setOnDismissListener(new OnDismissListener(){
public void onDismiss(){
//do what you need to here
}
});
popup.show(arg1);
This pattern should be familiar to you, its used everywhere in Android.

Android soft Keyboard not open in webView`

I m Using WebView in AlertDialog to authenticate user to twitter.
but When i click on field in webview ,android keyboard doesnt open.
here is my code that shows how i added webview in alert dialog.
i implicitly call android keyboard but it open keyboard behind alert dialog.
here is my code.
public static void webViewDialog(final String authorizationURL, final int type)
{
final boolean correctPin;
System.out.println("In webViewDialog");
container = new LinearLayout(context);
container.setOrientation(LinearLayout.VERTICAL);
container.setMinimumWidth(200);
container.setMinimumHeight(320);
webView = new WebView(context);
webView.setMinimumWidth(200);
webView.requestFocusFromTouch();
webView.setMinimumHeight(380);
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new TwitterWebViewClient());
webView.loadUrl(authorizationURL);
webView.setBackgroundColor(0xFFbbd7e9);
container.addView(webView);
Builder webDialog = new AlertDialog.Builder(context);
webDialog.setView(container).setTitle("Twitter Login")
.setPositiveButton("Ok", new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
if (type == 0)
{
twitterPinCodeDialog();
dialog.dismiss();
}
}
}).show();
showVirtualKeyboard();
}
public static void showVirtualKeyboard()
{
Timer timer = new Timer();
timer.schedule(new TimerTask()
{
#Override
public void run()
{
InputMethodManager m = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
if(m != null)
{
// m.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
m.toggleSoftInput(0, InputMethodManager.SHOW_IMPLICIT);
}
}
}, 100);
}
Here is my solution to this problem:
Put a dummy edit text, and set it's visibility to GONE, and add it to a containing LinearLayout, after adding the WebView to the layout.
Example:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
LinearLayout wrapper = new LinearLayout(this);
WebView webView = new WebView(this);
EditText keyboardHack = new EditText(this);
keyboardHack.setVisibility(View.GONE);
webView.loadUrl(url);
wrapper.setOrientation(LinearLayout.VERTICAL);
wrapper.addView(webView, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
wrapper.addView(keyboardHack, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
builder.setView(wrapper);
builder.create().show();
Once this is done, everything should work properly, and when you select an item in the WebView, the keyboard appears as expected.
I am using a PopupWindow with a WebView inside it and experienced the same problem, but if I set focusable to true in the parent the problem goes away:
popupWindow.setFocusable(true);
Hope this helps!
I had a similar issue and solved it in this way:
I override the onCreateView() method on the dialog fragment and define all view stuff configuration for my web view.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.webview, container, false);
// do some config
// some other stuffs
loginpage.loadUrl(url);
return view;
}
On the onCreateDialog() method i just add these.
#Override
public Dialog onCreateDialog(Bundle savedInstaceState) {
Dialog dialog = super.onCreateDialog(savedInstaceState);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
return dialog;
}
In my case i wanted to show a dialog with no title. So due the DialogBuilder take care of creating dialog's view i decided to override the onCreateView() and just call the super.onCreateDialog() and add my window configuration.
I also suffer from this problem, I solved this problem by customizing Dialog, here is my custom dialog code, hope so this is use full for you.
TwitterDialog fb=new TwitterDialog(this);
fb.abc();
//fb.dismiss();
class TwitterDialog extends Dialog {
Context context;
String url="https://accounts.google.com/ServiceLogin?service=mail&passive=true&rm=false&continue=https://mail.google.com/mail/&ss=1&scc=1&ltmpl=default&ltmplcache=2";
public TwitterDialog(Context context) {
super(context);
this.context=context;
}
void abc(){
LinearLayout mContent = new LinearLayout(context);
mContent.setOrientation(LinearLayout.VERTICAL);
final float scale = context.getResources().getDisplayMetrics().density;
float[] dimensions =new float[]{400.0f,500.0f};
addContentView(mContent, new FrameLayout.LayoutParams(
(int) (dimensions[0] * scale + 0.5f),
(int) (dimensions[1] * scale + 0.5f)));
FrameLayout.LayoutParams FILL =
new FrameLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.FILL_PARENT);
WebView mWebView = new WebView(context);
mWebView.setVerticalScrollBarEnabled(false);
mWebView.setHorizontalScrollBarEnabled(false);
mWebView.setWebViewClient(new WebClicent());
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.loadUrl(url);
mWebView.setLayoutParams(FILL);
mContent.addView(mWebView);
TwitterDialog.this.show();
}
class WebClicent extends WebViewClient{
#Override
public void onLoadResource(WebView view, String url) {
System.out.println("onLoadResource "+url);
super.onLoadResource(view, url);
}
#Override
public void onPageFinished(WebView view, String url) {
System.out.println("onPageFinished "+url);
//TwitterDialog.this.dismiss();
super.onPageFinished(view, url);
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
System.out.println("onPageStarted "+url);
super.onPageStarted(view, url, favicon);
}
}
}//TWitterDialog
The reason your keyboard may not be showing up, is probably because you are using a device that already has a hard keyboard. ANY DEVICE WITH A PHYSICAL KEYBOARD does not need to show a soft keyboard... That is why it is not showing. Because your device or your emulator has a physical hard keyboard.

Back pressed events with system alert window

I need to dismiss system alert window on back pressed and home button event.I have tried with onKeyEvent but in vain. As we can't capture the back pressed event in a service, how to achieve this?
Since it's a service that hosting an overlay window, It's a bit tricky solution but it is possible.
You should handle these 2 cases separately (overriding home button press, and back button press).
1. Overriding home button press:
Create this HomeWatcher class which contains a BroadcastReceiver that will notify when home button was pressed. Register this receiver only when your window comes up.
Android: associate a method to home button of smartphone
Inside your service onCreate method use this:
HomeWatcher mHomeWatcher = new HomeWatcher(this);
mHomeWatcher.setOnHomePressedListener(new OnHomePressedListener() {
#Override
public void onHomePressed() {
yourWindow.hide() //means: windowManager.removeView(view);
}
#Override
public void onHomeLongPressed() {
}
});
mHomeWatcher.startWatch();
2. Overriding back button press:
The idea is creating an empty layout as a data member of your window class,
and attach your view to it (even if its an inflated XML layout).
For example, this is gonna be your window class:
public class MyWindow
{
private WindowManager windowManager;
private WindowManager.LayoutParams params;
private View view;
// Add this empty layout:
private MyLayout myLayout;
public MyWindow()
{
windowManager = (WindowManager) context.getSystemService(context.WINDOW_SERVICE);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.your_original_window_layout, null);
// Add your original view to the new empty layout:
myLayout = new MyLayout(this);
myLayout.addView(view, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
}
// And show this layout instead of your original view:
public void show()
{
windowManager.addView(myLayout, params);
}
public void hide()
{
windowManager.removeView(myLayout);
}
}
And now create the MyLayout class to override the back button press:
public class MyLayout extends LinearLayout
{
private MyWindow myWindow;
public MyLayout(MyWindow myWindow)
{
super(myWindow.context);
this.myWindow = myWindow;
}
#Override public boolean dispatchKeyEvent(KeyEvent event)
{
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK)
{
if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0)
{
getKeyDispatcherState().startTracking(event, this);
return true;
}
else if (event.getAction() == KeyEvent.ACTION_UP)
{
getKeyDispatcherState().handleUpEvent(event);
if (event.isTracking() && !event.isCanceled())
{
// dismiss your window:
myWindow.hide();
return true;
}
}
}
return super.dispatchKeyEvent(event);
}
}
I know it's a bit complicated as I said since it's a system alert window hosted by a service, BUT it's working. I have the same issue as well and it has been solved exactly like that.
Good luck.
use below method to handle back button pressed.
public void onBackPressed()
{
super.onBackPressed();
}
You need to overwrite the onBackPressed method.
#Override
public void onBackPressed() {
super.onBackPressed(); // remove this if u want to handle this event
}
Use the code below
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
exitByBackKey();
//moveTaskToBack(false);
return true;
}
return super.onKeyDown(keyCode, event);
}
protected void exitByBackKey() {
AlertDialog alertbox = new AlertDialog.Builder(this)
.setMessage("Do you want to exit application?")
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
// do something when the button is clicked
public void onClick(DialogInterface arg0, int arg1) {
finish();
//close();
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
// do something when the button is clicked
public void onClick(DialogInterface arg0, int arg1) {
}
})
.show();
}
#Override
public void onBackPressed()
{
super.onBackPressed();
}
Declare this on your activity. super.OnBackPressed automatically calls back method in android. it will surely cancel your dialog.
in addition, your dialog must look like this.
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder1.setMessage("TEST DIALOG.\n");
builder1.setPositiveButton("Ok",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
Toast.makeText(MainActivity.this, "This Is test Dialog", Toast.LENGTH_SHORT).show();
}
});
AlertDialog alert11 = builder1.create();
alert11.show();
or you can set Negative button..
Hope this helps!
Define a custom layout and override dispatchKeyEvent, for example:
public class CustomSystemAlertWindow extends FrameLayout {
public static final String TAG = "CustomSystemAlertWindow";
private WeakReference<Context> mContext;
public CustomSystemAlertWindow(Context context) {
super(context);
mContext = new WeakReference<Context>(context);
// Set a background color to identify the view on the screen
this.setBackgroundColor(getResources().getColor(android.R.color.holo_red_light));
}
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event != null && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
Log.d(TAG, "back button pressed");
if (mContext != null && mContext.get() != null) {
WindowManager wm = (WindowManager) mContext.get().getSystemService(Context.WINDOW_SERVICE);
wm.removeView(this);
}
return true;
}
return super.dispatchKeyEvent(event);
}
}
Then add the view with this code:
CustomSystemAlertWindow customSystemAlertWindow = new CustomSystemAlertWindow(context);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
PixelFormat.TRANSLUCENT);
WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
wm.addView(customSystemAlertWindow, params);
When you press the back button the view will dismiss.
Show the Alert window through the Activity so you can detect it.
Implement the code to detect easily Back Button or Home Button pressed.
public class alertPopup extends Activity {
Context context;
final AlertDialog alertDialog;
String TAG = "your Activity Name"
boolean homePressed = false; // to detect the Homebutton pressed
#Override
public void onCreate(Bundle savedInstanceState) {
AlertDialog.Builder builder = newAlertDialog.Builder(YourActivity.this, R.style.AppCompatAlertDialogStyle);
builder.setTitle("AlertDialog Title");
..........
....... // Build ur AlertDialog
alertDialog= builder.create();
alertDialog.show();
//to detect Alert Dialog cancel when user touches outside the Dialog prompt
alertDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
Log.v(TAG,"Alert Dialog cancelled when user touches outside the Dialog prompt")
}
});
}
#Override
public void onBackPressed()
{
Log.v(TAG,"Back Button Pressed");
super.onBackPressed();
alertDialog.dismiss(); //dismiss the alertDialog
alertPopup.this.finish(); // Destroy the current activity
homePressed = false;
}
#Override
public void onResume() {
super.onResume();
homePressed = true; // default: other wise onBackPressed will set it to false
}
#Override
public void onPause() {
super.onPause();
if(homePressed) {
alertDialog.dismiss(); //dismiss the alertDialog
alertPopup.this.finish(); // Destroy the current activity
Log.v(TAG, "Home Button Pressed"); }
}
public void onDestroy(){
super.onDestroy();
}
}
Note:
Add this Permission in Android Manifest to show the alert Window .
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
Happy Coding :)
I understand that you are using the <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> permission for showing a floating view.
Using a floating view you can intercept the back button press, but the home button press cannot be intercepted (android won't let you primarily because of security reasons).
To intercept the back button press you need to add a wrapper when you inflate your floating view.
Your wrapper should look like this:
// Wrapper for intercepting System/Hardware key events
ViewGroup wrapper = new FrameLayout(this) {
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode()==KeyEvent.KEYCODE_BACK) {
hideAddNotesFloatingView();
return true;
}
return super.dispatchKeyEvent(event);
}
};
Then you add it to your floating view as a root:
mAddNoteFloatingView = mInflater.inflate(R.layout.floating_add_note, wrapper);
My complete code looks like this:
private void addFloatingView() {
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_PHONE,
0,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.CENTER | Gravity.LEFT;
params.x = 0;
params.y = 0;
// Wrapper for intercepting System/Hardware key events
FrameLayout wrapper = new FrameLayout(this) {
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode()==KeyEvent.KEYCODE_BACK) {
// Add your code for handling the back button press
return true; // Return true means that the event was handled
}
return super.dispatchKeyEvent(event);
}
};
mAddNoteFloatingView = mInflater.inflate(R.layout.floating_view, wrapper);
mWindowManager.addView(mAddNoteFloatingView, params);
}
It's simple. Follow these steps:
Create a view like Relative Layout, Linear Layout or Frame Layout Dynamically. 2. Override the dispatchKeyEvent while creating the view.
Add your original view into this dynamically created view with addView() method.
Add the dynamically created view to your Window Manager or Alert Dialog whichever you want.
In addition to #Eliran Kuta's solution, this is more simple answer for Back button.
val view = getAlertView()
val windowParam = WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT, // whatever
WindowManager.LayoutParams.WRAP_CONTENT, // whatever
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, // use WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY before Oreo
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, // whatever
PixelFormat.TRANSLUCENT // whatever
)
view.isFocusableInTouchMode = true
view.setOnKeyListener { view, keyCode, event ->
when (keyCode) {
KeyEvent.KEYCODE_BACK -> {
// do your work here
true
}
else -> false
}
}
val windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
windowManager.addView(view, windowParam)

Categories

Resources