Disabling first-run greeter on fresh android emulator - android

I am writing a test that requires launching application directly from launcher. Because I can't emulate it correctly by launching through intent.
The problem is that when I am running the test on a fresh emulator (I am using Travis CI, but it can be easily reproduced on my home PC) the emulator starts with the "first run" greeter overlay. Which blocks my uiautomator code from correctly launching the application.
I have tried to add some code to close that greeter but unfortunately it can appear with some delay, when my "greeter detecting and closing" code has already stopped working thinking that the coast is clear.
Is there any guaranteed way to disable that greeter? Some preference maybe or just an example of code that will reliably kill the greeter.

Have you tried using PackageManager.getLaunchIntentForPackage(..)? This will allow you to send the same Intent that the launcher uses to start your app. It should be equivalent to clicking on your application's launcher icon.
If you do need to go through the launcher, you can use a UiWatcher to dismiss the first-run overlay. Whenever UiAutomator can't find an element, it will call the checkForCondition(..) method for each registered UiWatcher and give you a chance to dismiss any overlays or dialogs that are getting in the way.

Apparently the greeter is called "cling". Searching though (rather old) code I found the following:
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android-apps/4.0.2_r1/com/android/launcher2/Launcher.java#Launcher.isClingsEnabled%28%29
private boolean isClingsEnabled() {
// TEMPORARY: DISABLE CLINGS ON LARGE UI
if (LauncherApplication.isScreenLarge()) return false;
// disable clings when running in a test harness
if(ActivityManager.isRunningInTestHarness()) return false;
return true;
}
And next stop is isRunningInTestHarness() at http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.2_r1/android/app/ActivityManager.java#ActivityManager.isRunningInTestHarness%28%29
public static boolean isRunningInTestHarness() {
return SystemProperties.getBoolean("ro.test_harness", false);
}
Which in turn leads to adb shell setprop ro.test_harness true. Which just works.

Related

Nativescript + Angular UI freezed after bring back from background on Android

My app have a background service (Android) which look periodicly for new data. If there are new data a notification is started. By tapping the notification a little native code piece is running and this will bring back to front the Nativescript app.
Snippet from the Kotlin class to bring back the Nativescript app:
val launchIntent: Intent? = packageManager.getLaunchIntentForPackage(applicationContext.packageName)
launchIntent?.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT or Intent.FLAG_ACTIVITY_SINGLE_TOP)
launchIntent?.setAction(ACTION_NOTIFICATION_AVAILABLE)
startActivity(launchIntent)
In the AppComponent class my listener for a AndroidApplication.activityResumedEvent will listen:
export class AppComponent implements OnInit {
constructor(
private router: Router,
private ngZone: NgZone,
) {}
ngOnInit(): void {
android.on(AndroidApplication.activityResumedEvent, (args) => this.ngZone.run(() => {
let intent = args.activity.getIntent();
if (intent.getAction() === com.sample.app.NotificationTapReceiver.ACTION_NOTIFICATION_AVAILABLE) {
this.router.navigate(['/notificationList']);
}
}));
}
}
Most of the times this code works as aspected. But in my opinion we have three diffrent situations:
App is in foreground and running when a notification is incomming and the use tap on it. => all works fine
The app is not running only the background service. If the user tap the notification the app will fully start and move to the notification list. => all works fine
Problem: The App is running but not in the foreground. By tapping the notification the app resume (without restart) to the front and navigate to the notification list BUT the user interface are freezed. By tapping the elements on the screen, the inside code are running (consoloe.log(...)) but no action on the UI. Maybee the UI are not freezed only the routing/navigation don't work.
I find the question Nativescript - How to bring app to foreground when notification is pressed but in my case there are no difference between android emulator and (not connected) real android device.
Tests with the flags to start the activity will change the behavior but not in the right way
# FLAG_ACTIVITY_SINGLE_TOP might be the best solution but the described error above is very annoying
launchIntent?.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT or Intent.FLAG_ACTIVITY_SINGLE_TOP)
# even the app is in foreground after a tap on the notification the app is fully restarts
launchIntent?.addFlags(FLAG_ACTIVITY_NEW_TASK)
Have anyone an idea where the problem is or which flags i have to set to prevent the current state and the fully working UI (with router/navigation)? Or do i have to modify the nativescript/angular code the better handle the resume event?
Not the best solution but when i was able to trim the flags to get the in the foreground running app still running and in the other two states (app dead or app in the background) a fully restart is initiated, at the moment this will be fine too.
Update: It look like, that the UI not freezed. I added a RadListView and i can scroll to the list, still the routing/navigate don't work. Even i use the this.routerExtensions.back() nor i use the this.router.navigate(['notificationDetail']).

How can I set my WatchFaceService as the default launch activity in Android Studio

I have a WatchFaceService (WatchFace) and every time I run my application it switches to the SimpleFace and then I have to set mine as the watchFace which ends up to be quite frustrating after many restarts.
To notice this does happen with the new Android Studio 2
I read around S.O. how to set the default activity but that does not do the same job as my WatchFaceService is not an activity but a service.
Also via the UI of Android Studio 2 it cannot be selected.
Is there a way to achieve this ? I think it might be difficult because actually it's not running an app, but setting the watch's Watchface at every run.
Any ideas?
The short answer is that this isn't possible. Your watch face is a Service, after all, so there's no way that it can be the default (launch) Activity for your app. They're completely different component classes.
But you can get close.
What you need to do is create a tiny little shell Activity that contains only the following code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = new Intent(WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER)
.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT,
new ComponentName(getPackageName(),
MyWatchFaceService.class.getName()));
startActivity(intent);
finish();
}
...where MyWatchFaceService is the class name of your watch face service (surprise). You'll also need to declare it in your manifest, of course:
<activity android:name=".FaceActivity"
android:enabled="true"
android:exported="true">
</activity>
Finally, configure your Wear module in Android Studio to launch FaceActivity when you run the app. This is under the Run menu, in Edit Configurations.
Having done that, run your app from AS onto the watch, and it'll open the watch face chooser on-device, with your face selected. From there, one tap will start it.
I can't see a way to eliminate that single tap, though.

How make a Android application that can't be closed

I'm developing an Android app for a company where those who will use it are the employees, for this reason the company asked me to develop an application that the user can not close, because if he will not use the smartphone for other purposes, but for this I need the Android native buttons do not interfere with the application.
I've deactivated the button to go back and put the application as Home.
#Override
     public void onBackPressed () {
         super.onBackPressed ();
     }
...
<category android: name = "android.intent.category.HOME" />
However if the user clicks the button that displays open applications, it can exit the application.
I researched a lot before creating resolve this question and realized several attempts to solve this problem.
One. I tried to create the same behavior as the MX Player has, when you use the lock to see a video, the MX Player is always on top of everything, leaving the user to see and click others places. However using this behavior does not i cant see My Dialogs nor Popup and also can not apply a thema, as in my case is not simply an activity is the entire application.
Reference links of my attempt
How to disable Home and other system buttons in Android?
http://www.piwai.info/chatheads-basics/
If anyone knows how to use that behavior MX Player, or if anyone knows any more how to make the user can not close the application, please help me, I know it's not just me who have this problem.
Any help is welcome!
My API is 16 - Android-4.1
Are your target devices rooted? If so, this article goes through the steps to make this possible. What you specifically ask about can be done by modifying the build.prop file to include the following line: qemu.hw.mainkeys=1. This will stop the soft-key navigation bar from ever showing up.
If the device you're running isn't rooted, I don't think that it's possible to do what you're asking.
The best way i found to the user can't access others apps, was to make a service that check which is the top activity, if don't is my then reopen my app.
ActivityManager manager = (ActivityManager) getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> runningTasks = manager.getRunningTasks(1);
if (runningTasks != null && runningTasks.size() > 0) {
ComponentName topActivity = runningTasks.get(0).topActivity;
if (!topActivity.getPackageName().startsWith("com.mypackage.")) {
Log.i("Top Activity", topActivity.getPackageName());
if (LocalCache.getInstance().isForceHome()) {
Intent intent = new Intent(HomeService.this, AuthLoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
handler.postDelayed(this, 500);
}
Old question, but I'm facing exactly same situation:
In-house App
Can't be close
I'm going to set App as a Launcher, and block top-dowm swipe to prevent status bar appear.
I think it's good enough for an in-house App ~

Move back to App after launching another App

I have a situation which I have been working on for close to a week now but can not come up with a working solution.
I have an app, which will launch a terminal window and run a command, the terminal used is Jack Palevich's Android-Terminal-Emulator (source code here) and the code used to launch a window is:
public boolean runCommand(String command) {
Intent intent = new Intent("jackpal.androidterm.RUN_SCRIPT");
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.putExtra("jackpal.androidterm.iInitialCommand", command);
if (mHandle != null) {
// Identify the targeted window by its handle
intent.putExtra("jackpal.androidterm.window_handle", mHandle);
}
startActivityForResult(intent, REQUEST_WINDOW_HANDLE);
return true;
}
Now this works fine, however the issue is that there are a number of times in the apps life that it will need to pass a command to this terminal window, and no user will be interacting with the device (i.e it will need to be automated).
When you launch a terminal window that window becomes the activity in view, therefore while my app still runs in the background any future calls to runCommand() will not happen until my app is brought back to view.
So I need to find a way to have my app become the app in view again once it has called runCommand() and started the terminal. I have tried a number of routes but with no really success, I guess the only really way forward will be to make changes to the terminal app itself, which I am happy to do (I have the source download and tested) but am just a little stuck as to where to look and what to change.
If you need any more info about my app or anything else, let me know!
Thank you

Create new intent in background

I am looking for a way to launch another app from within my app but so that the focus is not changed from my app to the app launched.
I.e currently I have the new app launched via a intent, however when this is carried out the new app is launched and becomes the app in view, I need it to be kept in the background with my app still in view.
The reason for this?
I am developing an application for internal use that will act like a lock-screen to the device so although things must happen in the background the 'lock-screen' must always be on top.
I have done some research into intents and launching other apps but can not find anything about what I need.
Hope you can help thank you!
Currently the terminal is called like this:
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setComponent(new ComponentName("jackpal.androidterm", "jackpal.androidterm.RemoteInterface"));
intent.setAction("jackpal.androidterm.RUN_SCRIPT");
intent.putExtra("jackpal.androidterm.iInitialCommand", cmdString);
The reason it needs to be running in the background is so that the app can run commands in terminal without the user having access, but then they 'unlock' the screen they need to then be able to view the terminal and what commands are being run etc
You can not startActivity in Background.Instead start the activity and minimise the activity(in your case this activity is of different application) using moveTaskToBack(true);
In your case, put a condition based on your intent and its params and use moveTaskToBack(true); so that activity will be minimised only when your application launches.
This won't be possible, you will have to start a background Service that does the actual work and only launch the Activity you want to navigate to once your foreground Activity is finished. Depending on your architecture, you can store the Activity to call when your foreground Activity is finished and change it from the service. That way you will have your desire behaviour without having to actually call the Activity.
In addition to the answer from #Meher, in the intent for your current starting activity, you can add the flag FLAG_FROM_BACKGROUND.
With this you get rid of the "blinking" effect (the one where your activity shows for one fraction of second while it discovers wether to go to background)

Categories

Resources