Android Background Service stops when screen is off - android

I am trying to scan beacons even when I quit my app using Service.
This is my code for the service.
public class MyService extends Service {
private static final String TAG = "MyService";
BluetoothManager bluetoothManager;
BluetoothAdapter bluetoothAdapter;
BluetoothLeScanner bluetoothLeScanner;
public MyService() {
}
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate called");
bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
bluetoothAdapter =bluetoothAdapter.getDefaultAdapter();
bleCheck(bluetoothAdapter);
bluetoothLeScanner.startScan(mScanCallback);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand called");
if (intent == null)
return Service.START_STICKY;
else{
}
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy called");
}
And these are the permissions i gave to app. I post all the permissions in case there might be problems.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
I used Wake_lock but it stops when the screen turns off. I cannot find the reason. And another question is that even though my phone OS is Android 9.0 the background service does not stop.
In the google document, I read that after Android Oreo, they strictly restrict app running on background but my app keeps on running.
Thanks for reading my question. Please help:)

Related

Android Wi-Fi Direct hotspot failure

I'm new to the Android platform and I want to create an app that creates a wi-fi hotspot so my microcontroller (esp32-c3) can connect to it. Further, the app should only contain a webview and be able to automatically determinate the IP-adres of the microcontroller so there can be established a Websocket connection to receive sensor data.
After much frustration setting up the IDE, I finally managed to build a simple app and and run it on my phone. My problem is that I always get a failure with reason code 0 (WifiP2pManager.ERROR) after creating a group, which is according to the documentation an internal error. I've tested this on multiple phones (Android 12 and 13) with the same result.
What I noticed is that there are barley examples available covering this topic. Am i making a mistake and is it possible to find out the detailed error message instead of seeing just htis generic error code?
This whole platform is difficult and frustrating. Can someone help me out? It must definitely be possible to create this on my phone, because with the app PdaNet+ I'm able to create a wi-fi direct hotpot that works.
public class MainActivity extends AppCompatActivity implements WifiP2pManager.ChannelListener, WifiP2pManager.ActionListener {
private final IntentFilter intentFilter = new IntentFilter();
private TextView tv1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv1 = this.findViewById(R.id.tv1);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
WifiP2pManager manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
WifiP2pManager.Channel channel = manager.initialize(this, getMainLooper(), this);
manager.createGroup(channel, this);
BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
tv1.append("\n" + action);
if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
tv1.append("\nWifi P2P is enabled");
} else {
tv1.append("\nWifi P2P is disabled");
}
} else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
tv1.append("\nCall WifiP2pManager.requestPeers() to get a list of current peers");
} else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
tv1.append("\nRespond to new connection or disconnections");
} else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
tv1.append("\nRespond to this device's wifi state changing");
}
}
};
registerReceiver(receiver, intentFilter);
}
#Override
public void onSuccess() {
tv1.append("\nGroup created successfully");
}
#Override
public void onFailure(int reason) {
tv1.append("\nFailed to create group (reason "+reason+")");
}
#Override
public void onChannelDisconnected() {
tv1.append("\nonChannelDisconnected");
}
}
Manifest:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
I finally solved the problem: it turned out the location permission was blocked. After giving access, the hotspot could get created.

ConnectivityService: ConnectivityService NetworkRequestInfo binderDied - application dies after lost internet connection

I have following permissions in AndroidManifest.xml
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.REBOOT" />
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
Then I have this BroadcastReceiver:
public class StartAfterRebootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (Properties.DEBUG) Log.d(TAG, "Receiver started");
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest.Builder builder = new NetworkRequest.Builder();
connectivityManager.registerNetworkCallback(
builder.build(),
new ConnectivityManager.NetworkCallback() {
#Override
public void onAvailable(Network network) {
if (Properties.DEBUG) Log.d(TAG, "Receiver running after connectivity up");
if (Properties.DEBUG)
Log.d(TAG, "Receiver starts service, probably once");
if (!UpdateService.isCurrentlyRunning()) {
if (Properties.DEBUG)
Log.d(TAG, "Receiver UpdateService is not running, try to start");
UpdateService.startService(context);
}
}
#Override
public void onLost(Network network) {
if (Properties.DEBUG)
Log.d(TAG, "Receiver not running after connectivity lost");
if (UpdateService.isCurrentlyRunning()) {
if (Properties.DEBUG)
Log.d(TAG, "Receiver UpdateService is running, sometimes need to redesigned stop service");
UpdateService.stopService(context);
}
}
}
);
}
}
I have Android TV box with Android 11, exactly I have two boxes from different vendors, on both is there only ethernet, not wifi, but on one of them is all working well, but on the other app start, starts foreground service correctly, when I plug out ethernet cable, service is correcty destroyed, but its all. App dies and over logcat I got this message:
05-18 22:05:03.444 548 852 D ConnectivityService: ConnectivityService NetworkRequestInfo binderDied(NetworkRequest [ LISTEN id=19, [ Capabilities: NOT_RESTRICTED&TRUSTED&NOT_VPN&FOREGROUND Uid: 10027 AdministratorUids: [] RequestorUid: 10027 RequestorPackageName: com.droidlogic.updater] ], android.os.BinderProxy#dc6b02d)
What I am doing wrong. I am sitting here over week and I cant see any mistake. Its system app compiled with android.
Thank you very much.
D
I moved ConnectivityService to Service and it helps.

Accessibility Service : AudioManager.AudioRecordingCallback on the AudioRecord or MediaRecorder

I am trying to record the audio via Accessibility as In Android developer Documentation mentioned
"The app can capture audio if it is an accessibility service."
Below is my code For Accessibility Service :
public class MyAccessibilityService extends AccessibilityService {
private static final String TAG="MyAccessibilityService";
public static final String START_RECORDING="START_RECORDING";
public static final String STOP_RECORDING="STOP_RECORDING";
private Context context;
MediaRecorder recorder;
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG,"MyAccessibilityService Salesken Started ...");
context=this;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null) {
String action = intent.getAction();
switch (action) {
case START_RECORDING:
Log.d(TAG,"Start Recording");
String contact = intent.getStringExtra("contact");
startRecorder(contact);
break;
case STOP_RECORDING:
Log.d(TAG,"Stop Recording");
stopRecorder();
break;
}
}
return super.onStartCommand(intent, flags, startId);
}
private void stopRecorder() {
if(recorder != null){
recorder.stop();
recorder.release();
}
}
private void startRecorder(String contact) {
String timestamp = new SimpleDateFormat("dd-MM-yyyy-hh-mm-ss", Locale.US).format(new Date());
String fileName =contact +"-"+timestamp+".pcm";
MediaSaver mediaSaver = new MediaSaver(context).setParentDirectoryName("AudioRecording").
setFileNameKeepOriginalExtension(fileName).
setExternal(MediaSaver.isExternalStorageReadable());
recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(mediaSaver.pathFile().getAbsolutePath());
try {
recorder.prepare();
} catch (IOException e) {
e.printStackTrace();
}
recorder.start();
}
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
}
#Override
public void onInterrupt() {
}
#Override
public void onDestroy() {
super.onDestroy();
stopRecorder();
}
}
Every time when i call START_RECORDING to my Accessibility Service i am getting below exception in the service
java.lang.RuntimeException: start failed.
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4222)
at android.app.ActivityThread.access$2100(ActivityThread.java:231)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1984)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7682)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:516)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
Caused by: java.lang.RuntimeException: start failed.
at android.media.MediaRecorder.native_start(Native Method)
I have below mention permission in my Manifest :
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
I am not sure how to use AudioManager.AudioRecordingCallback on the AudioRecord or MediaRecorder so that it can capture Voice Call Audio.
MediaRecorder.AudioSource.VOICE_CALL for system apps.
recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);
Capturing from VOICE_CALL source requires the Manifest.permission.CAPTURE_AUDIO_OUTPUT permission. This permission is reserved for use by system components and is not available to third-party applications.
VOICE_CALL Documentation
You can use VOICE_RECOGNITION source after activate Accesibility Service.
However, it will still not work in some countries or some physical devices. There are legal issues, so Samsung, Huawei, Xiaomi will act differently.
recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_RECOGNITION);

Broadcast DOWNLOAD_COMPLETE is not recieved if app is not running

Issue: broadcasts android.intent.action.DOWNLOAD_COMPLETE is received only if application is running or in background. If application is killed then broadcast never received.
AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
<uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER" />
<uses-permission android:name="android.permission.SEND_DOWNLOAD_COMPLETED_INTENTS" />
<receiver
android:name=".adapters.VideoListAdapter$VideoDownloadedReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
</intent-filter>
</receiver>
Receiver class
public static class VideoDownloadedReceiver extends BroadcastReceiver implements AsyncResponse {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("YES", "in receive");
}
}
Please note the I am facing this issue not in all devices.
Devices on which I am facing this issue: Lenevo A600, Asus Zenfone Max
Device on which it's working fine: Asus Zenfone 5 (cyanogenmod 13), Android Studio Emulator (Nexus 6p marshmallow), Samsung J7 Prime , Samsung j5, Nexus 5
I think the reason may be due to the customization ROM ,limited the broadcast,CM,ASOP,is the originally System.so,,,
if you want to receive broadcast even after app closed then you should use broadcast in service
following will help you to implement:-
https://stackoverflow.com/a/16824692/4246910
The receiver appears to be an internal class. Since the app is destroyed so is your internal receiver class which is part of a destroyed class.
I am basing this assumption because your manifest has
android:name=".adapters.VideoListAdapter$VideoDownloadedReceiver".
Separate the 'BroadcastReceiver' into its own class and it should work as expected.
As for working on some phones, I would check the other apps running and what kind of app suppression apps you may have running in the background which may be contributing to force closing your app.
you should have something like this. i looked at code and you have nested receeiver but you are not holding the service on.
Calling function to start the action
private void startDownloadService() {
Intent downloadIntent = new Intent(this, VideoDownloadReceiverService.class);
if (!VideoDownloadReceiverService.isRunning()) {
// My manifest has enabled="false" so i do this to turn it 'ON'
component = new ComponentName(CounterActivity.this, VideoDownloadReceiverService.class);
getPackageManager()
.setComponentEnabledSetting(component,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
// Start the service
startService(downloadIntent);
}
}
in separate file here is the service
public class VideoDownloadReceiverService extends Service{
private static boolean isRunning = false;
public VideoDownloadReceiverService(){
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// you may not need this since oyu register it in the Manifest. the fact the service is running
// should keep your app alive and receiving and unable to be shutdown
// but this is what i did
IntentFilter filter = new IntentFilter();
filter.addAction(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
receiver = new VideoDownloadReceiver();
registerReceiver(receiver, filter);
Notification notification = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentText("Viewer Text In Notification").build();
startForeground(MyConstants.NOTIFICATION_ID, notification);
isRunning = true;
return START_STICKY; // This is the line that keeps the service running no matter what
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy(){
unregisterReceiver(receiver);
super.onDestroy();
}
}
In separate file, here is the receiver
public class VideoDownloadReceiver extends BroadcastReceiver {
public VideoDownloadReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
PowerManager powerManager = (PowerManager) context.getSystemService(POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"com.example.johnbravado.zionwork");
wakeLock.acquire();
Toast.makeText(context, "in service", Toast.LENGTH_SHORT).show();
Log.i("YES", "service on receive");
wakeLock.release();
}
}

Android service bind trouble

Hello community I have the following problem.
My manifest file looks like the following.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.someCo.test"
android:versionCode="1"
android:versionName="1.0">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.location.network" />
<uses-feature android:name="android.hardware.location.gps" />
<uses-feature android:name="android.hardware.wifi" />
<uses-sdk android:minSdkVersion="8" />
<application android:icon="#drawable/ic_launcher" android:label="#string/app_name" >
<service android:name = ".BackgroundService" android:exported="true" />
</application>
</manifest>
my Activity's onCreate has the following line of code.
this.context.startService(new Intent(this.context, com.someCo.test.BackgroundService.class));
this.context.bindService(new Intent(this.context, com.someCo.test.BackgroundService.class), serviceConnection, Context.BIND_AUTO_CREATE);
my Activity also has the following private class.
private ServiceConnection serviceConnection = new ServiceConnection() {
public static final String TAG = "Service Connection Class";
public void onServiceConnected(ComponentName className, IBinder service) {
try {
com.someCo.test.BackgroundService.MyBinder binder = (com.someCo.test.BackgroundService.MyBinder)service;
backgroundService = binder.getService();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//backgroundService = ((BackgroundService.MyBinder) service).getService();
//Toast.makeText(context,"service connected", Toast.LENGTH_LONG);
Log.i(TAG, "onServiceConnected");
}
//#Override
public void onServiceDisconnected(ComponentName className) {
backgroundService = null;
}
};
my Service has the following.
private final IBinder binder = new MyBinder();
public class MyBinder extends Binder{
private static final String TAG = "MyBinder";
BackgroundService getService(){
Log.i(TAG, "get service");
return BackgroundService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
Log.i(TAG, "onBind destroyed");
return binder;
}
#Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "onUnbind destroyed");
return super.onUnbind(intent);
}
At this line I get the exception below the code.
(com.someCo.test.BackgroundService.MyBinder)service;
backgroundService = binder.getService();
java.lang.classCastException: android.os.BinderProxy.
Could someone kindly point me to my mistake, I can't seem to figure it out. Please forgive the very verbose code, as I was trying to be as explicit as possible in debugging this problem.
Thanks,
I don't know why you have written the code for start Service using both way(StartService and BindService)?
Here is the example for the Bind Service. you can refer this blog.
I have tried this thing my self several times. But from my experience, if you just need to bind the service to get some data from the service, there is no need to do so.
Just use localbroadcastmanager. It is sufficient to send the data from the service to application. It is quite easy, safe, less prone to memory leaks.

Categories

Resources