I want to make an activity that can be opened above ANY app.
Normally, even when the activity is set as dialog, when you switch to my app, you see my app, and in the background you see the launcher:
BUT, I want the app will go above any app like this: (made in photoshop):
I did see this question Creating a system overlay window (always on top), but in ICS there is no functionallity to the layout.
Furthermore, I want to give a dialog box from my app without minimizing the other app...
there are plenty of apps that show a floating view on top of everything like : airbrowser , LilyPad , Stick it , AirTerm , Smart Taskbar , aircalc ...
anyway , in order to achieve this feature , you must have a special permission called "android.permission.SYSTEM_ALERT_WINDOW" , and use something like that:
final WindowManager.LayoutParams param=new WindowManager.LayoutParams();
param.flags=WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
final View view=findViewById(R.id.my_floating_view);
final ViewGroup parent=(ViewGroup)view.getParent();
if(parent!=null)
parent.removeView(view);
param.format=PixelFormat.RGBA_8888;
param.type=WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
param.gravity=Gravity.TOP|Gravity.LEFT;
param.width=parent!=null?LayoutParams.WRAP_CONTENT:view.getLayoutParams().width;
param.height=parent!=null?LayoutParams.WRAP_CONTENT:view.getLayoutParams().height;
final WindowManager wmgr=(WindowManager)getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
wmgr.addView(view,param);
// TODO handle overlapping title bar and/or action bar
// TODO you must add logic to remove the view
// TODO you must use a special permission to use this method :android.permission.SYSTEM_ALERT_WINDOW
// TODO if you wish to let the view stay when leaving the app, make sure you have a foreground service running.
I'm one of the developers of the Tooleap SDK, and we also dealt with this issue.
Basically, you don't need to use the SYSTEM_ALERT_WINDOW to display an activity on top of another one. You can just display a regular "shrinked" Activity with a transparent background.
To make a "shrinked Activity, change the activity window layout params of height and width:
WindowManager.LayoutParams params = getWindow().getAttributes();
params.x = ...;
params.y = ...;
params.width = ...;
params.height = ...;
this.getWindow().setAttributes(params);
To make a transparent background add to your activity definition in the manifest file:
android:theme="#android:style/Theme.Translucent"
That way, you can create the illusion of a floating activity:
Note that only the foreground activity will be resumed, while the background one is paused. But for most apps this shouldn't be an issue.
Now all that remains is when to launch the floating activity.
Here is an example of a "floating" calculator app using a regular activity. Note that the activity below the calculator belongs to another app.
Related
I have challenged myself to code an in house app similar to Google's assistant voice tapping app. Everything is finished except the auto tap feature. When I launch the app it spins up a foreground service that draws a 8x8 grid that is always on top. Even when the main activity is minimized. The service uses an imageview that is set drawable. I then wrote an algorithm that draws a grid within it numbered 1 through 64. The user says which number to tap and the service does just that but nothing happens. I Log.wtf the tap coordinates x,y and it works perfectly when my main activity is open. when minimized it doesnt log the event OR its taping the wrong view.
Any suggestions?
Here is the code inside my custom window class that pops the window and sets the tap transperency so that taps pass through to the target app behind it. tPars is different for testing purposes. Both are window parameters.
`
mPars=new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
PixelFormat.TRANSLUCENT);
lInflater=(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
gridView = lInflater.inflate(R.layout.window_overlay,null);
iv = gridView.findViewById(R.id.iv);
ivHolder= gridView.findViewById(R.id.ivHolder);
((ImageView)iv).setImageDrawable(new Draw());
mPars.gravity=Gravity.CENTER;
mWManager=(WindowManager) context.getSystemService(WINDOW_SERVICE);
`
Ive even tried using System.exec("Touch X,Y"). Still same issue. Broadcast receivers wont work as the goal is to stay within the service WHILE using other apps. Its an auto tap assistant app like googles.
I would like to utilize this ---> MOTION EVENT
To reiterate, Once Main Activity spins up the service I no longer want or need it as the user will be using other apps. My app allows them to Tap/Scroll with their voice via the foreground service overlay.
Thanks in advance.
I tried MotionEvent, System.exec, and a few 3rd party APIs. It will only tap withing Main Activities view.
EDIT
Here is my tap and recognition code.
else if(sentence.get(0).equalsIgnoreCase("tap")){
mWManager.addView(gridView, mPars);
grid.draw(new Canvas());
tap(548F,946F);
}
and execution
private void tap(Float x, Float y) {
gridView.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis()+100, (int)MotionEvent.ACTION_DOWN, x, y, 0));
gridView.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis()+100, (int)MotionEvent.ACTION_UP, x, y, 0));
}
How to open an application inside another application within the latters boundaries in android? ie., similar to what iframe does in HTML.
You basically can't. It goes against the rules of Android. The most you can do is open a web page as part of an app. This is done using the webView. You can control the boundaries of the screen by setting the bounds of the webview in the xml file for the Webview.
public class WebViewFragment extends Fragment {
public static final String ARG_SECTION_NUMBER = "section_number";
public WebViewFragment() {
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View mainView = inflater.inflate(R.layout.fragment_facebook,
container, false);
WebView webView = (WebView) mainView.findViewById(R.id.webView1);
webView.setWebViewClient(new MyWebViewClient());
webView.getSettings().setSupportZoom(false);
webView.getSettings()
.setJavaScriptCanOpenWindowsAutomatically(true);
webView.getSettings().setAllowFileAccess(true);
webView.getSettings().setDomStorageEnabled(true);
webView.loadUrl(""); //URL needs to be entered in this line
return mainView;
}
}
Hope this helps :)
This is not possible because of security reasons. Previous versions of Android allowed this with System-grade permissions (ones that most developers will never get to use), but it was rarely used and is not in the SDK anymore as far as I know.
Some manufacturers implement additional functionalities like Samsung's Mini Apps (if I remember the name correctly) which may be opened in a floating window above other apps. You can also draw your own app over another using a service (like Facebook messenger does). But there is no way to force a third party app to do any of these things.
However, every time you open an application from your application, the process of the new one will have the invoker's process assigned as parent. This allows you, to some extend, check if this other app was opened from your app.
Also, your app will not die when opening a new one, but will simply be "below it". If you need some kind of data from the other app, you may start it forResult. This way the other app will "know" you are expecting a defined result from it, so it will process some data and pass it back to your app (which will reappear after the other one is finished preparing the result).
It could be possible if use the android property
android:launchMode="singleTask while declaring your activity in the AndroidManifest.xml (inside the activity element).
If you so so, if you minimize your app and launch it again (from background or from app icon from the list of apps), it would still show you the new app.
I am not sure if the result would be as per your desired effect.
I have this code which allows me to set the current device wallpaper as my activitys background.
public void wallpaperBackground()
{
WallpaperManager wallpaperManager = WallpaperManager.getInstance(this);
Drawable wallpaperDrawable = wallpaperManager.getDrawable();
View root = findViewById(R.id.home_view);
root.setBackground(wallpaperDrawable);
}
The problem is, if I change the wallpaper via settings it doesn't update on my app and I'm left with the previous wallpaper. How can I fix this?
It is quite easy actually:
Just call your wallpaperBackground() method in onResume() in your activity.
This will automatically apply the correct wallpaper when the activity resumes after the user comes back from another app.
So I am working on an Android application using Android 4.0 Library.
One of the activities of this application is made up of a RelativeLayout that has an image background and a toggle button.
The background image of the layout must change when the user toggles the button.
So it must be changed from inside the activity.java class:
if (toggleButton.isChecked()){
// Change the background of the activity to image 2 (for example)
}
else{ // when toggle button is off
// Change it back to image 1
}
Please help me with this. Thank you :)
You use the method, setBackground in the View class:
if (toggleButton.isChecked()){
// Change the background of the activity to image 2 (for example)
View myView = this.findViewById(yourViewId);
myView.setBackgroundResource(yourImage);
}
else{ // when toggle button is off
// Change it back to image 1
// Change the background of the activity to image 2 (for example)
View myView = this.findViewById(yourViewId);
myView.setBackgroundResource(yourOtherImage);
}
What I would like to have is an activity indicator, which is displayed after my app is up and running, but while GWT is making AJAX calls.
For example have a look at following site : http://www.foodtrucksmap.com/#
Any ideas on how to achieve it?
You can use an activity indicator from here, they are animated gifs so you can display one like this:
<g:Image ui:field="activityImage"/>
MyResources resources = GWT.create(MyResources.class);
this.activityImage.setResource(resources.activityImage());
and in your resources interface you would set the image:
public interface MyResources extends ClientBundle{
// use the actual path to your image
#Source("../resources/images/activityImage.gif")
ImageResource activityImage();
}
When you make your async calls:
loadingImage.setVisible(true);
and in the callback:
loadingImage.setVisible(false);
I had to deal with the same kind of stuff few days back. The way I did was, created an Icon and Overlayed on the map.
Icon icon = Icon.newInstance("loading.gif"); // load you gif as icon
MarkerOptions options = MarkerOptions.newInstance();
options.setIcon(icon);
Marker indicator = new Marker(point, options);
So before the Async call and after you map is up, just add the icon to the map using
map.addOverlay(indicator);
and after the Async call remove the overlay using
map.removeOverlay(indicator);
I am not sure how correct this approach is, but this is what I did and it worked.