I'm in the process of developing an Android app for which I need to add a button on the incoming call screen. Is it possible to add a new button to the existing incoming call screen or should I create a custom screen specific to my app?
Edit:
I want to add a button in addition to the Answer and Decline buttons in the screen that appears when there is an incoming call.
I was looking for the same funcionality and found this open source project, http://code.google.com/p/incomingcallplus/
Haven't played with it yet, but seems to do what you're looking for.
Yes and No.
No, you can't add a new button to an existing app. But Yes, you can replace that app (in this case, the dialer) with one that has the button you want. When users install your app, they'll pick whether they want to use your app or the built-in dialer app to make and receive calls.
You probably want to add something like the following to your main.xml:
<Button android:id="#+id/helloButton" android:layout_height="wrap_content" android:layout_width="wrap_content" text="Hello Button" />
Then in your 'Launcher' activity, you'll need to assign a handler to handle clicks, etc.
If you want to do this on the default dialer screen then I don't think that's possible without disabling controls of the dialer and having your transparent activity over the dialer; user will be able to interact with your activity and can only use the dialer on clicking the back button.
You might want to go with the custom design.
public void addInvitePopup(final String number,Context c){
//check if pref is ok with invite in call
// if(!Preferences.getInstance(c.getInviteInCall())){return ; }
// sets the WindowManager
WindowManager wm = (WindowManager) c.getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT |
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
params.x = 250;
params.height = LayoutParams.WRAP_CONTENT;
params.width = LayoutParams.WRAP_CONTENT;
params.format = PixelFormat.TRANSLUCENT;
final Context ct =c;
params.gravity = Gravity.TOP;
params.setTitle("Testing");
LinearLayout ly = new LinearLayout(c);
ly.setOrientation(LinearLayout.VERTICAL);
Button inviteButton = new Button(c);
inviteButton.setClickable(true);
inviteButton.setBackgroundDrawable(c.getResources().getDrawable(R.drawable.icon));
inviteButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(v.getContext(), "adding to blacklist..", Toast.LENGTH_LONG).show();
v.setBackgroundDrawable(ct.getResources().getDrawable(R.drawable.images));
v.setClickable(false);
// sendMessage(v, number);
//Track this event:
//MixPanelTracking.setPropKeyValue(getApplicationContext(), null, null, "Add friend - During Call");
}
});
also dont forget to add permission : android.permission.SYSTEM_ALERT_WINDOW in your manifest file
Related
I am working on an android application where I use a custom view to my window. I have the following code to do it :-
private void systemOverlayFullScreen()
{
WindowManager manager = ((WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE));
//manager.removeView(view);
WindowManager.LayoutParams localLayoutParams = new WindowManager.LayoutParams();
// changed to alerts or overlay from system_error
localLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
// set width and height of overlay originally -1
localLayoutParams.width = -1;
// changed gravity to bottom so as to hide the stop the home button press; originally -1
localLayoutParams.height = -1;
localLayoutParams.y = -getNavigationBarHeight();
localLayoutParams.x = 0;
localLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
// this is to enable the notification to recieve touch events
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
// Draws over status bar
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
// you can change it to transparent
//localLayoutParams.format = PixelFormat.TRANSLUCENT;
localLayoutParams.alpha = 0.3f;
CustomViewGroup view = new CustomViewGroup(this);
manager.addView(view, localLayoutParams);
}
When I click the home button and then relaunch my app again, the previously added custom view is still present. I want to remove it when the app relaunches.
I have tried doing :-
#Override
protected void onRestart() {
// TODO Auto-generated method stub
super.onRestart();
if(view.getWindowToken() != null)
{
Toast.makeText(getApplicationContext(), "View present", Toast.LENGTH_SHORT).show();
WindowManager manager = ((WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE));
manager.removeView(view);
}
else
{
Toast.makeText(getApplicationContext(), "View not present", Toast.LENGTH_SHORT).show();
}
}
But this doesnot work.
Can anyone tell me how to remove a view dynamically when the app starts ?
Your code will execute exactly as specified when you open the app everytime. Meaning it will add the CustomView once the app is opened. The onRestart method takes into account the activity restart not the whole app. You could perform a check before adding the view. i.e the user enters there name and you store it SharedPreferences. Then you can test if the user signed up and if they did it means when theres a restart the CustomView won't be added to your window.
I'm new to android and I require to have a list of image buttons in an activity which are created based on the data in a database. I haven't created anything like this in android before and so far I've been using HTML tables to show my data in a grid view. I'm not asking for any special code, I'm just clueless on how to implement this. I wanna know what the best approach is.
One problem I've faced is with the click events(in the way I've been doing them so far) which do not take in any EventArg, so I can't get the name of the button out of them.
If you're sure that the OnClickListener instance is applied to a Button, then you could just cast the received view to a Button and get the text:
public void onClick(View v) {
// 1) Possibly check for instance of first
Button b = (Button)v;
String buttonText = b.getText().toString();
}
// create the layout params that will be used to define how your button will be displayed
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
// Create Button
final Button btn = new Button(this);
// Give button an ID
btn.setId(someinteger);
btn.setText("Add Text");
// set the layoutParams on the button
btn.setLayoutParams(params);
I'm trying to emulate a software keyboard for a domain specific input. I'm using a PopupWindow to gather the input and transfer it to the underlying EditText. Unfortunately, the PopupWindow is modal, so the user cannot switch from one EditText to another as they can with the usual software keyboard. I've looked into setting the FLAG_NOT_TOUCH_MODAL flag, but I'm not sure when or to what it should be applied to get the behavior I'm looking for.
My code for launching the PopupWindow looks like:
myEdit.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
pw = myKeyboard.getPopupWindow((EditText) v);
pw.showAtLocation(Main.this.findViewById(R.id.main), Gravity.BOTTOM, 0, 0);
}
});
I tried changing it to the following, but this only resulted in the runtime exception: java.lang.RuntimeException: view android.widget.LinearLayout#40526268 being added, but it already has a parent
myEdit.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
pw = myKeyboard.getPopupWindow((EditText) v);
WindowManager.LayoutParams wlp = getWindow().getAttributes();
wlp.gravity = Gravity.BOTTOM;
wlp.flags = wlp.flags | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
getWindow().addContentView(pw.getContentView(), wlp);
pw.showAtLocation(Main.this.findViewById(R.id.main), Gravity.BOTTOM, 0, 0);
}
});
I'm also looking into setOutsideTouchable, but so far I haven't gotten anywhere.
Any pointers on how I can create a modeless PopupWindow? I would be willing to use some other modeless widget.
A PopupWindow seems a bit heavy for what you're trying to do, and as you're finding out you're having to fight against it to do what you want. Why not just implement your keyboard as a View and stick it in your layout, then hide/show it?
Is there anyway to prevent users from sliding the status bar (expand) or collapsing back?
I'm trying out a lockscreen replacement and seems like it's a must-have feature. Is there any possible way to do it without requiring root privileges?
You can actually prevent the status bar from expanding, without rooting phone. See this link. This draws a window the height of the status bar and consumes all touch events.
Call the following code just after onCreate().
public static void preventStatusBarExpansion(Context context) {
WindowManager manager = ((WindowManager) context.getApplicationContext()
.getSystemService(Context.WINDOW_SERVICE));
Activity activity = (Activity)context;
WindowManager.LayoutParams localLayoutParams = new WindowManager.LayoutParams();
localLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
localLayoutParams.gravity = Gravity.TOP;
localLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
// this is to enable the notification to recieve touch events
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
// Draws over status bar
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
localLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
//https://stackoverflow.com/questions/1016896/get-screen-dimensions-in-pixels
int resId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");
int result = 0;
if (resId > 0) {
result = activity.getResources().getDimensionPixelSize(resId);
}
localLayoutParams.height = result;
localLayoutParams.format = PixelFormat.TRANSPARENT;
customViewGroup view = new customViewGroup(context);
manager.addView(view, localLayoutParams);
}
public static class customViewGroup extends ViewGroup {
public customViewGroup(Context context) {
super(context);
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.v("customViewGroup", "**********Intercepted");
return true;
}
}
Short answer: this is impossible!
Now should you be interested to know why this is impossible:
There are two permissions for manipulating the system status bar, EXPAND_STATUS_BAR and STATUS_BAR. The former can be requested by any application, but the later is reserved for applications signed with the platform signature (system applications, not third-party). It is possible to expand/ collapse the system status bar (see "How to open or expand status bar through intent?") but note that reflection is required because the StatusBarManager class is not part of the SDK. The disable method, which is used by the Android dialer to prevent the status bar from being expanded, cannot be accessed by an application without the aforementioned STATUS_BAR permission.
Sources: personal experience :-)
First of all, it's impossible to modify the Status Bar if your app is not signed with the phone's rom certified, if you try to modify it you'll get an Security Exception.
Update: In new APIs the method is "collapsePanels" instead of "collapse".
The only way I've found after several hours of work is by overriding the "onWindowFocusChanged" method of the activity and when it loses the focus (maybe the user has touched the notifications bar), force to collapse the StatusBar, here is the code (working on a Defy+ 2.3.5).
You need to declare the following permission on the manifest:
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR"/>
And override the following method:
public void onWindowFocusChanged(boolean hasFocus)
{
try
{
if(!hasFocus)
{
Object service = getSystemService("statusbar");
Class<?> statusbarManager = Class.forName("android.app.StatusBarManager");
Method collapse = statusbarManager.getMethod(Build.VERSION.SDK_INT > 16 ? "collapsePanels" : "collapse");
collapse.setAccessible(true);
collapse.invoke(service);
}
}
catch(Exception ex)
{
}
}
Update: You will have to use your own custom Alert Dialog by overriding it their onWindowFocusChanged method too, because Alert Dialogs have their own focus.
This actually can be done via a little hack that I accidentally discovered, but requires the permission android.permission.SYSTEM_ALERT_WINDOW:
What you do is add a view the exact size of the status bar directly to the WindowManager with the certain parameters that covers the status bar and prevents it from receiving touch events:
View disableStatusBarView = new View(context);
WindowManager.LayoutParams handleParams = new WindowManager.LayoutParams(
WindowManager.LayoutParams.FILL_PARENT,
<height of the status bar>,
// This allows the view to be displayed over the status bar
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
// this is to keep button presses going to the background window
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
// this is to enable the notification to recieve touch events
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
// Draws over status bar
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
PixelFormat.TRANSLUCENT);
handleParams.gravity = Gravity.TOP;
context.getWindow().addView(disableStatusBarView, handleParams);
This will basically create a transparent view over the status bar that will receive all the touch events and block the events from reaching the status bar and therefore prevents it from being expanded.
NOTE: This code is untested, but the concept works.
I tried the solutions mentioned by GrantLand and PoOk but both didn't work in my case. Though, Another solution Clear/Hide Recent Tasks List did the trick for me. I am writing a launcher app for which I had to disable a recent applications menu so user cannot open a locked app from it. Also, I had to prevent against notification bar expansion and this trick made me achieve both. Override OnWindowFocusChanged method in your activity and check if this is what u wanted.
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
Log.d("Focus debug", "Focus changed !");
if(!hasFocus) {
Log.d("Focus debug", "Lost focus !");
Intent closeDialog = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
sendBroadcast(closeDialog);
}
}
For a lockscreen Why don't you just use the following in your main activity:
#Override
public void onAttachedToWindow() {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
}
If the user doesn't have a secure lockscreen set the app will let the user pull the status bar down and open activities but that doesn't matter as the user obviously doesn't want a secure screen anyway.
If the user does have a secure locksreen set then the app will show the status bar but will not allow interactions with it. This is because the phone is still actually locked and only your activity is allowed to operate until the user unlocks the phone. Also closing your app in anyway will open the standard secure lockscreen. All this is highly desirable because you don't have to spend all that time coding secure features that you can't guarantee will be as secure as the stock ones.
If you really don't want the user to be able to interact with the status bar, maybe you can leave out the flag FLAG_DISMISS_KEYGUARD call. Then just before you are about to unlock the phone set the flag like I showed in the first block. I don't know if this last part works but it's worth a try.
Hope that helps
Sorry but it does not work. using FLAG_LAYOUT_IN_SCREEN prevents you from catching any touch events.
And BTW:
to add a view to the window use the window manager:
WindowManager winMgr = (WindowManager)getSystemService(WINDOW_SERVICE);
winMgr.addView(disableStatusBar, handleParams);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
public class MessageDisplayDialog extends Dialog implements OnClickListener
{
public MessageDisplayDialog(Context context, String title, String message)
{
super(context);
setTitle(title);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.color.default_text_color);
Log.v(getClass().getSimpleName(), "MessageDisplayDialog");
LinearLayout objLinearLayout = new LinearLayout(context);
LinearLayout objButtonLayout = new LinearLayout(context);
TextView objMesaageView = new TextView(context);
objMesaageView.setText(message);
objMesaageView.setTextColor(Color.WHITE);
objMesaageView.setGravity(Gravity.CENTER_HORIZONTAL);
objMesaageView.setPadding(0, 0, 0, 10);
Button okButton = new Button(context);
okButton.setText(" OK ");
okButton.setOnClickListener(this);
okButton.setWidth(100);
objButtonLayout.addView(okButton);
objButtonLayout.setGravity(Gravity.CENTER_HORIZONTAL);
objButtonLayout.setPadding(0, 5, 0, 0);
objButtonLayout.setBackgroundColor(Color.LTGRAY);
objLinearLayout.setOrientation(LinearLayout.VERTICAL);
objLinearLayout.addView(objMesaageView);
objLinearLayout.addView(objButtonLayout);
setContentView(objLinearLayout);
//LayoutParams param = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
//this.addContentView(objLinearLayout, param);
}
public void onClick(View v)
{
this.dismiss();
}
}
But the Dialog is not showing bar below the Title, how to crack it.
I think your question has already been answered in this thread
Android - change custom title view at run time
please do some searching and accept answers before asking questions.
I think the horizontal border between the title and the message in the built in dialogs is part of AlertDialog, not the base Dialog class, although I could be totally wrong about that. Regardless, whenever I attempt to do something similar to what you are doing, that horizontal line disappears and I've never been able to get it back.
I ended up just writing my own dialog layout XML file and creating my own horizontal line using a <shape> drawable. It's actually fairly painless to create your own completely custom Dialog layouts like this, and gives you more control over the look of your dialogs.
This is old I know, but FYI the solution of drawing your own line on a custom dialog is not compatible with ICS.
It will display both your line and the line that ICS is now including by default. So you'd get two lines on the screen.
use two lines of code to remove dialoge title
Dialog dialog = new Dialog(this);
dialog.requestWindowFeature(dialog.getWindow().FEATURE_NO_TITLE);