How to make the app running when screen closed in android device - android

My app MainActivity have banner、video,but when using gotoSleep,after amonent,open the screen,they will stop play and scroll,how to make the app running when screen open after screen close
my code is :
public ScreenUtils(Context contx) {
this.mContext = contx;
this.pManager = (PowerManager)this.mContext.getSystemService("power");
this.wakeLock = this.pManager.newWakeLock(268435462, "TAG");
this.wakeLock.setReferenceCounted(false);
this.wakeLock.acquire();
}
public boolean lcdPowerOff() {
if (this.wakeLock.isHeld()) {
this.wakeLock.release();
}
this.pManager.goToSleep(SystemClock.uptimeMillis());
return true;
}
public boolean lcdPowerOn() {
this.wakeLock.acquire();
return true;
}

don't use wakeLock, Android's power control is very strict now
When you reopen the app, you can restart the player in the onResume lifecycle

Related

react native kiosk mode listen to unpinning from device buttons

I want to implement kiosk mode on react native (android). I have implemented the functionality to pin/unpin application and check if lock task mode is active using activityManager.getLockTaskModeState, startLockTask & stopLockTask.
The problem is i cannot track when user unpin the app by pressing recencts/back buttons.
i tried to add event listener with following code without success
public void registerLifecycleEventObserver() {
UiThreadUtil.runOnUiThread(new Runnable() {
#Override
public void run() {
AppCompatActivity activity = (AppCompatActivity) reactContext.getCurrentActivity();
activity.getLifecycle().addObserver(KioskModeModule.this);
}
});
}
#Override
public void onStateChanged(#NonNull LifecycleOwner source, #NonNull Lifecycle.Event event) {
boolean isKioskEnabled = isLockTaskModeActive();
if (this.isKioskEnabled != isKioskEnabled) {
this.isKioskEnabled = isKioskEnabled;
WritableMap args = Arguments.createMap();
args.putBoolean("isKioskEnabled", isKioskEnabled);
sendEvent("onKioskStateChange", args);
}
}
Any idea on how i can listen to kiosk mode state change?

How to check if application is running on background?

I am using firebase to send notifications to the application and based on the notification the user will be directed to some activity. so far so good, the problem I am having is that if the application is running on background the activity that will be shown is the main activity but I can not quite managed it to do it.
I believe there ar several questions like this, but do not quite get the answer I am looking for.
Any help or suggestion would be great, thanks
try
/**Flag to determine if the Activity is visible*/
private static boolean activityVisible;
private static boolean activityDestroy;
/**Is the application actually visible on the mobile screen*/
public static boolean isActivityVisible(){
return activityVisible;
}
/**Is the application actually destroyed*/
public static boolean isActivityDestroy(){
return activityDestroy;
}
/**Is the application actually destroyed*/
public static void activityDestroy(boolean isDestroy){
activityDestroy = isDestroy;
}
/**Is the application actually in the background*/
public static boolean isActivityInBackground(){
return !activityVisible;
}
/**Change the state of the Application to resume*/
public static void activityResumed() {
activityVisible = true;
}
/**Change the state of the Application to paused*/
public static void activityPaused() {
activityVisible = false;
}
and then for checking
Application app = ((Application)getApplicationContext());
boolean visible = app.isActivityVisible();
Android 10 (API level 29) and higher place restrictions on when apps can start activities when the app is running in the background. These restrictions help minimize interruptions for the user and keep the user more in control of what's shown on their screen.
You could use importance field of ActivityManager.
Below the method for Xamarin using by C#, but it's pretty similiar to Java.
P.S.: If you want I could port that code to Java
public static Importance GetAppState(Context context, string packageName)
{
try
{
var manager = (ActivityManager)context.GetSystemService(Context.ActivityService);
var processes = manager.RunningAppProcesses;
if (processes != null)
foreach (var process in processes)
if (process.ProcessName.Equals(packageName))
return process.Importance;
}
catch
{
}
return Importance.Gone;
}

Entering in PIP Mode with the application minimized (Android Studio)

My application makes a call to the server which may take a few seconds. The user can minimize the App before receiving the response from the server.
So what I am trying to do is that if the App is minimized when it receives the response from the server, it will go to PIP mode.
When I try to enter Pip mode with the application minimized I get this error:
java.lang.IllegalStateException: Activity must be resumed to enter picture-in-picture
The error occurs when this line is executed:
enterPictureInPictureMode();
Thanks.
Need to check whether the special permission Picture-in-Picture is given before entering the mode.
AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
if (manager != null) {
int modeAllowed = manager.unsafeCheckOpNoThrow(OPSTR_PICTURE_IN_PICTURE, Process.myUid(),
context.getPackageName());
if (modeAllowed == AppOpsManager.MODE_ALLOWED) {
// Enter picture-in-picture
}
}
If you are using rn-android-pip libary:
import android.app.AppOpsManager;
import android.content.Context;
import android.os.Process;
public void enterPictureInPictureMode() {
if (isPipSupported) {
AppOpsManager manager = (AppOpsManager) reactContext.getSystemService(Context.APP_OPS_SERVICE);
if (manager != null) {
int modeAllowed = manager.checkOpNoThrow(AppOpsManager.OPSTR_PICTURE_IN_PICTURE, Process.myUid(),
reactContext.getPackageName());
if (modeAllowed == AppOpsManager.MODE_ALLOWED) {
if (isCustomAspectRatioSupported) {
PictureInPictureParams params = new PictureInPictureParams.Builder()
.setAspectRatio(this.aspectRatio).build();
getCurrentActivity().enterPictureInPictureMode(params);
} else {
getCurrentActivity().enterPictureInPictureMode();
}
}
}
}
}
According to the doc:
Also, specify that your activity handles layout configuration changes so that your activity doesn't relaunch when layout changes occur during PiP mode transitions.
Switching to PiP mode triggers configuration changes, and this causes the Activity to be recreated, says going through stopped -> destroyed -> created -> ...
And we can find how Activity decides whether it can enter PiP mode or not:
https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/app/Activity.java
final void performStop(boolean preserveWindow, String reason) {
...
// Disallow entering picture-in-picture after the activity has been stopped
mCanEnterPictureInPicture = false;
...
}
public boolean enterPictureInPictureMode(#NonNull PictureInPictureParams params) {
...
if (!mCanEnterPictureInPicture) {
throw new IllegalStateException("Activity must be resumed to enter"
+ " picture-in-picture");
}
...
mIsInPictureInPictureMode = ActivityClient.getInstance().enterPictureInPictureMode(
mToken, params);
return mIsInPictureInPictureMode;
}
So you may need to check you AndroidManifest again to ensure you have already properly handled configuration changes to avoid Activity recreation:
<activity android:name="VideoActivity"
android:supportsPictureInPicture="true"
android:configChanges=
"screenSize|smallestScreenSize|screenLayout|orientation"
...

Unlock android device not working while call ACTION_CALL intent

I am receiving a push notification, On that, calling a foreground service.
From the service, I am calling one Activity.
Here, I have 2 functionality.
1. Sound alarm for emergency
2. Call using ACTION_CALL.
Both are working fine if device unlocked.
But if a device is locked with password or pattern it did not work when push receives.
Below code to unlock the device. this method is called from onStart.
private void unlockDevice() {
KeyguardManager loKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
Window loWindow = this.getWindow();
if (Common.isAboveAPI27()) {
setShowWhenLocked(true);
setTurnScreenOn(true);
} else if (Common.isAboveAPI26()) {
loWindow.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
loWindow.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
dismissKeyguard(loKeyguardManager);
} else {
if (loKeyguardManager != null) {
KeyguardManager.KeyguardLock loKeyguardLock = loKeyguardManager.newKeyguardLock("FullWakeUps");
loKeyguardLock.disableKeyguard();
}
loWindow.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD); // Deprecated in 26
loWindow.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); // Deprecated in 27
loWindow.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); // Deprecated in 27
}
//Keep screen on
loWindow.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
#RequiresApi(api = Build.VERSION_CODES.O)
private void dismissKeyguard(KeyguardManager loKeyguardManager) {
if (loKeyguardManager != null) {
loKeyguardManager.requestDismissKeyguard(SOSCallAndAlarmActivity.this, new KeyguardManager.KeyguardDismissCallback() {
#Override
public void onDismissError() {
super.onDismissError();
Log.i(TAG, Build.VERSION.SDK_INT + " : onDismissError");
}
#Override
public void onDismissSucceeded() {
super.onDismissSucceeded();
Log.i(TAG, Build.VERSION.SDK_INT + " : onDismissSucceeded");
}
#Override
public void onDismissCancelled() {
super.onDismissCancelled();
Log.i(TAG, Build.VERSION.SDK_INT + " : onDismissCancelled");
}
});
}
}
The below method is call in onDestroy to reenable the lock:
private void reEnabledKeyguard() {
KeyguardManager loKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
if (loKeyguardManager != null) {
KeyguardManager.KeyguardLock loKeyguardLock = loKeyguardManager.newKeyguardLock("FullWakeUps");
loKeyguardLock.reenableKeyguard();
}
Window loWindow = this.getWindow();
loWindow.addFlags(WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);
}
Code to initiate the call.
public void callOnNumbers(String fsPhoneNumber) {
Intent loCallIntent = new Intent(Intent.ACTION_CALL);
loCallIntent.setData(Uri.parse("tel:" + fsPhoneNumber));
//callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // tried this but not helped.
if (ActivityCompat.checkSelfPermission(CallAndAlarmActivity.this,
android.Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
Log.i(TAG, "call phone permission not granted");
return;
}
startActivity(loCallIntent);
}
Strange is when this method opens the call screen blink and again displays the password screen on lock screen simply press back button I can see the call screen.
I need to know one more thing, even I set all app killing option and disabled battery optimization. the same code did not execute on push receive.
When device inactive half an hour and if push receives, the above code did not even turn on light. when I click on the lock/unlock button I can see my screens properly. even I press it after 30 seconds of push receives time.
The problem facing from android N.
Additional
When the ACTION_CALL intent calls it to execute my activities onPause and I did not add any code in onPause and I can see one error in logcate
2020-04-27 16:23:47.400 25826-25826/app.safety E/ActivityThread: Performing stop of activity that is already stopped: {app.safety/app.safety.CallAndAlarmActivity}
java.lang.RuntimeException: Performing stop of activity that is already stopped: {app.safety/app.safety.CallAndAlarmActivity}
at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:4089)
at android.app.ActivityThread.handleStopActivity(ActivityThread.java:4177)
at android.app.ActivityThread.-wrap24(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1648)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6687)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:810)
2020-04-27 16:23:47.400 25826-25826/app.safety E/ActivityThread: ActivityClientRecord{paused=true, stopped=true, hideForNow=false, startsNotResumed=false, isForward=false, pendingConfigChanges=0, onlyLocalRequest=false, preserveWindow=false, Activity{resumed=false, stopped=true, finished=false, destroyed=false, startedActivity=false, temporaryPause=false, changingConfigurations=false}}
Thanks
I wonder if it has something to do with the Background Execution Limit. in Android. I would recommend looking at this article.
https://medium.com/exploring-android/exploring-background-execution-limits-on-android-oreo-ab384762a66c
I hope this is of any help.

Launching app from home screen will launch it on top of an existing instance if it was launched previously from the app screen, vise versa

There seems to be a bug of some sort with the play store installer, whenever I try to resume my app from the home screen icon rather than the app screen it will launch again on top of my already running app. This is true for the other way around
I've tried this code
if (!isTaskRoot()) {
final Intent intent = getIntent();
final String intentAction = intent.getAction();
if (intent.hasCategory(Intent.CATEGORY_LAUNCHER)
&& intentAction != null
&& intentAction.equals(Intent.ACTION_MAIN)) {
finish();
}
}
But all it does it crash the app if it tries launching in the fashion I stated.
My manifest is also set to
android:launchMode="singleTask"
I found that if I take exactly the same APK and install it using "adb install", my app works correctly and as I expect.
However, if I (or my users) download the apk and install it from the Downloads, I find the behaviour described above, namely a new instance of my Activity being created on the stack when the user navigates to home and then back to the app via the launcher. This can be verified with "adb shell dumpsys activity "
I fixed the issue by using the following at my Launch Activity
ublic class StartupActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (needStartApp()) {
Intent i = new Intent(StartupActivity.this, GameActivity.class);
startActivity(i);
}
finish();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
// this prevents StartupActivity recreation on Configuration changes
// (device orientation changes or hardware keyboard open/close).
// just do nothing on these changes:
super.onConfigurationChanged(null);
}
private boolean needStartApp() {
final ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
final List<RunningTaskInfo> tasksInfo = am.getRunningTasks(1024);
if (!tasksInfo.isEmpty()) {
final String ourAppPackageName = getPackageName();
RunningTaskInfo taskInfo;
final int size = tasksInfo.size();
for (int i = 0; i < size; i++) {
taskInfo = tasksInfo.get(i);
if (ourAppPackageName.equals(taskInfo.baseActivity.getPackageName())) {
// continue application start only if there is the only Activity in the task
// (BTW in this case this is the StartupActivity)
return taskInfo.numActivities == 1;
}
}
}
return true;
}
}

Categories

Resources