I'm currently porting a Flash game to OUYA (an Android powered device) via Adobe AIR.
Most of the work has been done already; it's packaged up and runs on Android devices.
However! When I double-tap the middle button to return to the system home screen (which I believe to be the equivalent of pressing the home button on an Android mobile), the app doesn't seem to pause or exit, and the music can still be heard.
Does anyone have any tips on how to suspend or exit an AIR app when the home button is pushed? Thanks!
Try listening for Event.DEACTIVATE. That dispatches when Flash/AIR loses focus in the context of the operating system/browser. Should be exactly what you are looking for. You should attach it to NativeApplication.nativeApplication, I believe. Attaching it to the Stage might also work, but I'm not entirely sure.
If you want to listen for the app to exit, listen for Event.EXITING on NativeApplication.
I ended up doing this:
this.stage.addEventListener(flash.events.Event.ACTIVATE, onResume, false, 0, true);
this.stage.addEventListener(flash.events.Event.DEACTIVATE, onPause, false, 0, true);
In my init, and then:
private function onPause(event:flash.events.Event):void
{
SoundMixer.stopAll();
}
private function onResume(event:flash.events.Event):void
{
FP.world = new MenuWorld();
}
Related
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']).
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.
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 ~
I have made a Flash Air game. While playing it, if I press the Home button on my Android device, I get to the phone's menu yet I still get to listen to the game's music, which means that the game still keeps on fully working.
I would like my app to pause when not in the foreground.
I've seen these codes but apparently I'm doing something wrong cause they aren't working probably...
NativeApplication.nativeApplication.addEventListener(Event.DEACTIVATE, handleApplicationDeactivated);
NativeApplication.nativeApplication.addEventListener(Event.ACTIVATE, handleApplicationActivated);
I've listed the:
import flash.events.Event;
import flash.desktop.NativeApplication;
Could you help me with the proper code?
The code below will run the onPause when you press the home button, and onResume when you get back in your app.
SoundMixer.stopAll(); will stop ALL sounds that are playing.
this.stage.addEventListener(flash.events.Event.DEACTIVATE, onPause, false, 0, true);
this.stage.addEventListener(flash.events.Event.ACTIVATE, onResume, false, 0, true);
private function onPause(event:flash.events.Event):void
{
//here save your games state.
//then stop ALL sound from playing with the following line:
SoundMixer.stopAll();
//Remember to import flash.media.SoundMixer;
}
private function onResume(event:flash.events.Event):void
{
//here you start the sounds again, for example:
sound.play();
}
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