I am trying to do WebRTC, all is working fine but there seems to be an issue, that is, if the screen remains off for more than a minute the audio stops recording, meaning the audio from device stops until I switch the screen on once again.
What I have tried?
1) I have tried setting webSettings.setMediaPlaybackRequiresUserGesture(false); it does no good to the problem.
2) I have also tried adding a wakelock in the activity in which I am doing WebRTC but it also didn't work.
Here are the permissions declared in Manifest:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
Here in activity, I am granting permission for the microphone in WebChromeClient:
#Override
public void onPermissionRequest(final PermissionRequest request) {
request.grant(request.getResources());
}
What I want?
I want to be able to continue call without disrupting the user to turn screen back on again. Please point me in right direction.
Thanks!
Update: I tried loading the WebRTC url in Chrome and the same thing is happening, that is, audio stops recording from my device.
Update 2: Adding log when audio stops coming from the device.
2019-08-06 17:18:47.266 4332-22405/? V/APM_AudioPolicyManager: getAudioPolicyConfig: audioParam;outDevice
2019-08-06 17:18:47.266 4332-22405/? V/APM_AudioPolicyManager: getNewOutputDevice() selected device 2
2019-08-06 17:18:47.266 4332-22405/? V/APM_AudioPolicyManager: ### curdevice : 2
2019-08-06 17:18:47.307 4332-22405/? V/APM_AudioPolicyManager: AudioPolicyManager:setRecordSilenced(uid:99066, silenced:1)
2019-08-06 17:18:47.308 4332-22405/? V/APM_AudioPolicyManager: AudioPolicyManager:setRecordSilenced(uid:11556, silenced:1)
Update 3: Tried initializing WebView in a Foreground Service still same result.
Update 4: Tried a demo call on https://appr.tc/ using Chrome(76.0.3809.132). Observed the same result.
Update 5: Tried a demo call using Firefox and it worked FLAWLESSLY which lets me thinking that is it a Chromium bug?
Update 6: Filled a bug report
Android will automatically destroy your activity on a few minutes after leaving foreground that will cause the audio recording to turn off.
I have working with webrtc on android, if you want to create call and video call with webrtc on Android, I suggest to use native webrtc and implement everything related to webrtc on foreground service. Foreground service will ensure your recorder and camera to keep running event when activity is destroyed.
For reference, here the google sample for implementing webrtc native
https://webrtc.googlesource.com/src/+/master/examples/androidapp/src/org/appspot/apprtc
You should work on keeping the screen on in that activity during the call and prevent if from dimming.
Use this:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
and after your call is done:
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
Check your Chrome/Android version due to this issue with WebRTC on Android:
Issue 513633: WebRTC call in Chrome on Android will be cut off 1 min after screen off
WebRTC is supported by default in Chrome so... it should work.
BTW, if you dont't need WebRtc or want try to implement in a background service...
Interest readings:
1 - recording-when-screen-off
As the post says, keep in mind:
To call:
startForeground();
Use START_STICKY:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
2 - how to implement a recorder
As the post says, keep in mind permissions:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Background services with Apache Cordova
With cordova and a webview you need to use a plugin to run code in background as a service too.
Take a look at this link:
cordova plugin
Another choice with Cordova is to do your own plugin like this:
custom plugin - background video recorder
Obviously, it's no usual task, because all your implementation, it's just a WebView. Which very hard to align with such long living task and lifecycle inside Android. For ex. every VoIP application we did, had services in background, to keep connection alive, with wake locks. This was only one way to ensure about stability of the call.
However, I think you could try to do the same. By managing your WebView work inside Service. For this purpose, you could consider moving some calling logic into another view, and starting new Service and creation new Window. This will ensure your Window will be alive, during all the lifecycle of the Service.
Smth like.
public class ServiceWithWebView extends Service {
#Override
public void onCreate() {
super.onCreate();
final WindowManager windowManager = (WindowManager)
getSystemService(WINDOW_SERVICE);
params = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY);
final LinearLayout view = new LinearLayout(this);
view.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout
.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT));
WebView wv = new WebView(this);
wv.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout
.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
view.addView(wv);
wv.loadUrl("http://google.com");
windowManager.addView(view, params);
}
}
It is possible that the problem is in battery optimization. The device cleans up the background processes and finds there your audio recording screen working on the background. try to add the app to the list of Battery Best Performance list. Search how to do that on your device.
For my case even important background tasks as accessibility service is forced to stop under that battery optimization algorithm. To allow my service to work all the time, the user should add the app to the whitelist of battery best performance rule.
I hope it can help you.
Related
The problem seems to be known, but I could not find the right solution.
I will describe the scenario:
There is an application making requests to the API. In some FirstActivity, a request is made to the API, upon positive result of which startActivity () is called in SecondActivity. The problem is that if, while sending the request, the application is minimized to the background (that is, startActivity () will be called in the background), then:
If android version> = 29 then startActivity () basically won't work. The one following startActivity () finish () will work and upon restarting the application will restart (which is logical)
If the android version is < 29, then startActivity () will fire and bring this SecondActivity to the foreground.
Based on this, the question is. How can I force the application, regardless of version, to transition between activities and not bring them to the front?
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivity(intent);
finish();
As per documentation
Android 10 (API level 29) and higher place restrictions on when apps
can start activities when the app is running in the background.
Workaround : In specific situations, your app might need to get the user's attention urgently, such as an ongoing alarm or incoming call. You might have previously configured your app for this purpose by launching an activity while your app was in the background.
To provide similar behavior on a device running Android 10 (API level 29) or higher, complete the steps described in this guide.
you can show a high-priority notification with a full-screen intent.
More Details
Updated answer for new requirement: For your comment
(Well, please tell me how to make startActivity () in the background start the activity also in the background, and not raise the application from the background)
you can add a LifecycleObserver that will be notified when the LifecycleOwner changes state.
Inside your activity api response callback use the following condition
if (lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) {
// Activity is in resumed state, Open new activity immediately
} else {
// else add a LifecycleObserver that will be notified when the LifecycleOwner changes state
lifecycle.addObserver(object : DefaultLifecycleObserver {
override fun onStart(owner: LifecycleOwner) {
super.onStart(owner)
// remove observer immediately so that it will not get triggered all the time
lifecycle.removeObserver(this)
// Activity is in start state again, Open new activity here
}
})
}
As soon as I receive a push notification from my app I want to trigger the KeyguardManager to launch the fingerprint/pass code screen to open the phone from lock screen so that person can enter the phone and unlock the device.
I want to trigger this programmatically similar to when we click on any notification from lock screen we get the fingerprint/pass-code screen.
I did a lot of RnD but didn't find any solution, this is one of the challenging use case task given to me in class, I have been exploring a lot from quite few weeks with no success at all.
Did tried Broadcast receiver with BiometricManager and many things with no success, any lead will be very helpful.
As soon as you receive push message, onNotificationReceived() (or some other method if you use some 3rd party libs) method gets called as below. from there, you can launch your Main screen where you have written biometric/unlocking code.
class MyReceiver : PushReceiver {
override fun onNotificationReceived(message: Message) : Boolean {
//Launch your MainActivity where you can show Unlock screen.
return super.onNotificationReceived(message);
}
}
https://developer.android.com/preview/privacy/background-activity-starts
From this, it results that my payment app, which shows an Activity when a NFC transaction is performed, will not be able anymore to show anything to the user.
Has anyone have a clue what would be the new approach ?
Thanks!
I currently use the NFC service and it starts an Activity intent.
Intent intent = new Intent(mApplicationContext, PaymentActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
mApplicationContext.startActivity(intent);
The Activity should be shown. It works now, but from Android Q, it won't
According to the link, if you are having a HostApduService, then your app should work the same in Android Q.
If that is not your case, the simplest work around is to get "Draw over other apps" permissions. You can open activities if the app has been granted the SYSTEM_ALERT_WINDOW permission by the user. I have tested this and working.
Technically, you are showing something on top of other apps without user's interaction, so this might be the right way to go.
I'm trying to implement in my android app the Google Maps Places API.
When a button is clicked it opens the place picker, the picker works fine (you can move around, zoom in and out, search and go to current location), until when you try to click on the "Select this location" button; when the button is clicked a blank screen opens, and the only option is to close the app.
The same happens when the back button is pressed (either the one the navigation bar, or the one in the AppBar)
Image: Inside the Place Picker Activity
Image: Blank Screen
It was working fine a few weeks ago, then it stopped working, one day ago it started working again, and today it stopped working.
Code to open Place Picker:
private void openPlacePicker() {
Log.i(TAG, "open place picker");
PlacePicker.IntentBuilder builder = new PlacePicker.IntentBuilder();
try {
startActivityForResult(builder.build(this), PLACE_PICKER_REQUEST);
}
catch (GooglePlayServicesRepairableException | GooglePlayServicesNotAvailableException e) {
e.printStackTrace();
}
}
And yes I've added a permission check for ACCESS_FINE_LOCATION, before executing the function.
Code for on Activity Result:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.i(TAG, "onActivityResult");
if (requestCode == PLACE_PICKER_REQUEST) {
if (resultCode == RESULT_OK) {
final Place place = PlacePicker.getPlace(this, data);
(...)
My logs don't show any errors, and the OnActivityResult Logs aren't called:
D/libgps: proxy_gps_stop: called.
D/libgps: proxy_gps_status_cb: called.
D/libgps: proxy_gps_status_cb: called.
I/art: Background partial concurrent mark sweep GC freed 58725(4MB) AllocSpace objects, 23(2MB) LOS objects, 40% free, 14MB/23MB, paused 1.422ms total 101.850ms
D/gpsd: WakeLock(Release,GPSD)
I/Auth: [AuthDelegateWrapper] Service intent: Intent { cmp=com.google.android.gms/.auth.account.authenticator.DefaultAuthDelegateService }.
I/Auth: [AuthDelegateWrapper] Service intent: Intent { cmp=com.google.android.gms/.auth.account.authenticator.DefaultAuthDelegateService }.
I/Auth: [AuthDelegateWrapper] Service intent: Intent { cmp=com.google.android.gms/.auth.account.authenticator.DefaultAuthDelegateService }.
D/NetworkSecurityConfig: No Network Security Config specified, using platform default
I/GCoreUlr: Successfully inserted 1 locations
I/WifiHAL: Got channel list with 11 channels
I/WifiHAL: Got channel list with 9 channels
I/WifiHAL: Got channel list with 13 channels
W/ActivityManager: Launch timeout has expired, giving up wake lock!
My Manifest Meta Data and Permissions:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<application
(...)
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="AIza(...)" />
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
I've check in the Google Console Page, the package name and the SHA-1 fingerprint are correct.
When I'm at Overview > Google Maps APIs > Google Places API for Android > Usage, it shows no usage what so ever, when it should be showing some, because as I said previously, one day ago it was working and I used it.
This issue has happen on my Nexus 9 (Android N), and on the Moto G3 (Android M).
Note: On the Moto G it would work the first time, user would click a button, place picker opens, user clicks on picker's "Select Location" button, goes to previous activity everything works fine; but if he clicks on the button to open the picker again, and he tries to click on picker's "Select Location" button again, he would go to the blank screen, and would have to close the app and try again).
TLDR;
The Place Picker in my android app goes to a blank screen when I try to select a location or leave the Place Picker Activity.
Thanks
As noted by my earlier comment, I had the exact same problem earlier today.
What solved it for me was replacing:
compile 'com.google.android.gms:play-services:9.0.0'
with
compile 'com.google.android.gms:play-services-location:9.0.0'
This change was suggested from this Stack post
Note: If you're using more than just the location from the play-services library, make sure to include the other components like
compile "com.google.android.gms:play-services-games:9.0.0"
compile "com.google.android.gms:play-services-plus:9.0.0"
compile "com.google.android.gms:play-services-ads:9.0.0"
This error timeout has expired, giving up wake lock! means your Activity is taking to long to start. If you are doing a lot of processing on the UI thread, Android kills your application. You should use AsyncTask for any processing intensive stuff. Activity cannot be displayed because it is still trying to complete execution; meanwhile the ActivityManager has timed out.
AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
Sample implementation of Asyntask:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
}
protected void onProgressUpdate(Integer... progress) {
}
protected void onPostExecute(Long result) {
}
}
For blank screen when selecting locations, make sure you have the permission in your manifest file.
uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/ >
uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
How can I force stop an app with Java? I'm trying to build a memory cleaner that can help clean out background processes.
I know there is a way to kill the process of an app, but when you go to the running list, the app is still there even after you have killed it. And I have tried a lot of similar memory cleaning apps, only one of them can totally force stop apps but it has so many useless notifications - very annoying.
P.S.: When you go to Settings -> Apps, you will see a list of apps. Click on one of these apps and you end up on the app's info. There is a button named "force stop". By clicking on it, the app is killed. I want to perform that kind of action in my app. How can this be done?
get the process ID of your application, and kill that process onDestroy() method
#Override
public void onDestroy()
{
super.onDestroy();
int id= android.os.Process.myPid();
android.os.Process.killProcess(id);
}
or
getActivity().finish();
System.exit(0);
and if you want to kill other apps from your activity, then this should work
You can send the signal using:
Process.sendSignal(pid, Process.SIGNAL_KILL);
To completely kill the process, it's recommended to call:
ActivityManager.killBackgroundProcesses(packageNameToKill)
before sending the signal.
Please, note that your app needs to own the KILL_BACKGROUND_PROCESSES permission. Thus, in the AndroidManifest.xml, you need to include:
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
Try to use following code
finish(); // for stopping Current Activity
// add this line for Removing Force Close
#Override
protected void onDestroy() {
// closing Entire Application
android.os.Process.killProcess(android.os.Process.myPid());
super.onDestroy();
}
}
May be this solution will help you Force Close an app programmatically