WearOS Off Body Event is not always triggered - java

I'm developing a simple app for WearOS. This app consists of the app itself, which just shows an image and two services. One is a service, does NFC card emulation and the other simply listens for the off body event, and resets some values, whenever the watch is taken off. This works well while I'm debugging and also for a some time when started normally.
However, after a few hours, the watch can be taken off, without my app getting the event. I suspect, that the OS is killing the service and not restarting it, despite the START_STICKY flag. The watch is not coupled with a phone and is not running other apps.
This is the code of my service:
public class MySensorService extends Service
{
private static final String TAG = "MySensorService";
private SensorManager sensorManager;
private Sensor mOffBody;
public MySensorService()
{
Log.i(TAG, "Sensor service was created.");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.i(TAG, "Sensor service starting.");
sensorManager = (SensorManager) getApplicationContext().getSystemService(SENSOR_SERVICE);
mOffBody = sensorManager.getDefaultSensor(TYPE_LOW_LATENCY_OFFBODY_DETECT, true);
if (mOffBody != null) {
sensorManager.registerListener(mOffbodySensorListener, mOffBody,
SensorManager.SENSOR_DELAY_NORMAL);
}
Log.i(TAG, "Sensor service was started.");
return START_STICKY;
}
private void onWatchRemoved()
{
Log.i(TAG, "Watch is not worn anymore");
Intent intent = new Intent(this, MyAPDUService.class);
intent.putExtra("UserID", 0);
Log.d(TAG,"starting service");
startService(intent);
}
private void onWatchAttached()
{
Log.i(TAG, "Watch is now worn");
}
private final SensorEventListener mOffbodySensorListener = new SensorEventListener()
{
#Override
public void onSensorChanged(SensorEvent event)
{
if (event.values.length > 0)
{
if (event.values[0] == 0) // 0 = Watch is not worn; 1 = Watch is worn
{
onWatchRemoved();
}
else
{
onWatchAttached();
}
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int i)
{
}
};
#Override
public void onDestroy()
{
super.onDestroy();
Log.i(TAG, "Sensor Service destroyed");
}
}

Related

android studio use camera in background

I'm new to the Android studio and I was trying to make the camera work in the background. I just want the camera to get the feed activity of it but when I'm trying to open the app it just automatically stops. The camera is usually working fine if it's in the MainActivity but when I transfer it to my camera service the app automatically stops when I open.
public class CameraService extends Service implements CameraBridgeViewBase.CvCameraViewListener2{
private static final String TAG = "MainActivity";
private JavaCameraView mOpenCvCameraView;
private Mat mRgba;
public CameraService(){
}
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
#Override
public void onManagerConnected(int status){
switch (status) {
case LoaderCallbackInterface.SUCCESS:{
Log.i(TAG, "OpenCV loaded successfully");
mOpenCvCameraView.enableView();
}
break;
default:{
super.onManagerConnected(status);
}
break;
}
}
};
#Override
public void onCreate() {
mOpenCvCameraView = (JavaCameraView) mOpenCvCameraView.findViewById(R.id.javacameraview);
mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
mOpenCvCameraView.setCvCameraViewListener(this);
mOpenCvCameraView.setCameraIndex(CameraBridgeViewBase.CAMERA_ID_FRONT);
Toast.makeText(this, "The new Service was Created", Toast.LENGTH_LONG).show();
}
private void setContentView(int activity_main) {
}
#Override
public void onStart(Intent intent, int startId) {
Toast.makeText(this, " Service Started", Toast.LENGTH_LONG).show();
}
#Override
public void onDestroy() {
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
super.onDestroy();
if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
}
#Override
public void onCameraViewStarted(int width, int height) {
mRgba = new Mat(height, width, CvType.CV_8UC4);
}
#Override
public void onCameraViewStopped() {
mRgba.release();
}
#Override
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
return inputFrame.rgba();
}
}
can someone give me some tips or pinpoint my problem?
Google’s Android Pie update came with a new feature that prevents apps from running in the background from using the camera. This feature ensures that you don’t live in fear of malicious apps (that remain active in the background when your screen is turned off) capturing potentially unwanted scenes of you or your loved ones without authorization.
error in your code: you are using an unassigned object to find the id
if you are doing it for illegal purposes, don't do this -this type of problem is not liked by the StackOverflow community.

Eventbus don't running in background with service

I had an eventbus problem and tried a lot of ways.
I use the service to schedule my app, I will post an event to Eventbus in App.Activity every time.
RefreshService.java
Runnable run = new Runnable() {
#Override
public void run() {
if (instanceNetwork.isOnline(RefreshService.this)) {
Log.d("LOG_SERVICE_POST", "run: ");
EventBus.getDefault().postSticky(RUNNING);
}
mHandler.postDelayed(this::run, timeRefresh);
}
};
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (timeRefresh == null) {
timeRefresh = instanceSharedPreferences.getTimeRefresh(Setting.KEY_AUTO_REFRESH, getString(R.string.TIME_REFRESH_DEFAULT));
}
mHandler.postDelayed(run, timeRefresh);
return super.onStartCommand(intent, flags, startId);
}
Activity App
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_app);
Intent intent = new Intent(this, RefreshService.class);
startService(intent);
}
#Override
protected void onStart() {
super.onStart();
if (!EventBus.getDefault().isRegistered(this)) {
EventBus.getDefault().register(this);
}
}
#Override
protected void onDestroy() {
if(EventBus.getDefault().isRegistered(this)){
EventBus.getDefault().unregister(this);
}
AppDatabase.destroyInstance();
super.onDestroy();
}
#Subscribe(sticky = true, threadMode = ThreadMode.BACKGROUND)
public void onMessageEvent(Boolean isRun) {
if (isRun == RefreshService.RUNNING) {
Log.d("LOG_REFRESHED", "onMessageEvent: ");
runnableRefresh.run();
}
}
Currently, Service and Eventbus can run normally, but when the app is off, only the Service will run (Subscribe does not receive the event).
What I want is that Subscribe can receive my event even when the app is off.

Variable is showing value as null even when I had set already value of it

I have created background service to connect my socket server, it works background while app is off, when user open the app MainActivity join to my service class and it looks fine, my service can change fragment in main activity, but when it get disconnected and want to change fragment in main activity then app crash
check my MainActivity
public class MainActivity extends AppCompatActivity {
private clientService mclientService;
private Intent mServiceIntent;
private final FragmentManager fm = getFragmentManager();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mclientService = new clientService(this);
mServiceIntent = new Intent(this, mclientService.getClass());
if (!isMyServiceRunning(mclientService.getClass())) {
startService(mServiceIntent);
}
}
public Fragment changeFragment (Fragment cls) {
FragmentTransaction ft = this.fm.beginTransaction();
ft.replace(R.id.bodyFrame, cls);
ft.commit();
return cls;
}
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
Log.i ("isMyServiceRunning?", true+"");
return true;
}
}
Log.i ("isMyServiceRunning?", false+"");
return false;
}
}
and the clientService:
public class clientService extends Service {
private Socket mSocket;
{
try {
IO.Options opts = new IO.Options();
opts.query = "_d=jakistakiid";
mSocket = IO.socket("http://10.0.2.2:3000", opts);
} catch (URISyntaxException e) {}
}
public clientService(MainActivity main) {
super();
mainAttach(main);
}
public clientService() {
}
public MainActivity mMain;
public void startIt(){
Log.i("eroapp", "Service Started");
if(mSocket != null) {
mSocket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.i("eroapp", "connected");
}
}).on(Socket.EVENT_DISCONNECT, new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.i("eroapp", "dc:"+mMain);
onDC();
}
});
mSocket.connect();
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
startIt();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Intent broadcastIntent = new Intent(this, restartReceiver.class);
sendBroadcast(broadcastIntent);
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
// CLIENT FUNCTIONS //
private void onDC(){
Log.i("eroapp", "DC:"+mMain);
}
private void mainAttach(MainActivity m) {
mMain = m;
Log.i("eroapp","Main created!");
if(!mSocket.connected()) {
mMain.changeFragment(new offlineFragment());
}else{
mMain.changeFragment(new singFragment());
}
}
}
looks fine, when i close app activity my service restarts and run in background, it says in logcat:
2019-11-17 02:41:22.686 17458-17458/com.example.secmsg I/eroapp: Service Started
2019-11-17 02:41:22.803 17458-17483/com.example.secmsg I/eroapp: connected
when i open app again, my service is already running, so its run only function mainAttach in clientService, and then service run changeFragment function in main activity, works great, but
when I get disconnected from server it says mMain is null ; < and logcat output:
2019-11-17 02:41:31.654 17458-17499/com.example.secmsg I/eroapp: dc:null
2019-11-17 02:41:31.654 17458-17499/com.example.secmsg I/eroapp: DCnull
The mclientService you created on the MainActivity is not the same as the clientService that was started by the Android system when you called startService(intent). All services created and started by the Android system by using the service class' empty constructor, therefore, clientService#mainAttach will never be called. Take a look at this answer for more information.
If you want to directly interact with the service on the MainActivity, you might want to bind the service to your activity. Check out the documentation about bound services here.
Another thing... It looks like you're planning to directly control the MainActivity from the service using the reference to the activity. Please never do that and use broadcasts instead. Good luck!

Why not call onActivityResult in Activity on Android

In my application i want a Recording Screen and for this I write below code.
After running application, there's no call to my Recorder service and after using Log.e it still does not show me logs?
I write Recording code into onActivityResult.
For this I used countDownTimer and I want, when this timer has finished, for the recording to start.
For checking if it works I used Log.e and it shows a log into onFinished code (for timer), but does not show any logs into onActivtyResult code
My Activity code:
public class RecordingActivity extends BaseActivity {
private TextView txtTesterCounter;
Thread thread;
private int counter;
private CountDownTimer countDownTimer;
private MediaProjection mMediaProjection;
private MediaProjectionManager mProjectionManager;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tester_tutorial_count_down);
init();
reverseTimer(4).start();
//Create video direction
createDir();
}
private void init() {
txtTesterCounter = findViewById(R.id.txtTesterCounter);
counter = 3;
//Acquiring media projection service to start screen mirroring
mProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
}
private CountDownTimer reverseTimer(int second) {
return countDownTimer = new CountDownTimer(second * 1000, 1000) {
#SuppressLint("SetTextI18n")
#Override
public void onTick(long millisUntilFinished) {
if (millisUntilFinished <= 800) {
onFinish();
} else {
int second = (int) (millisUntilFinished / 1000);
txtTesterCounter.setText(App.enToFa(second + ""));
}
}
#Override
public void onFinish() {
if (mMediaProjection == null && !isServiceRunning(RecorderService.class)) {
//Request Screen recording permission
startActivityForResult(mProjectionManager.createScreenCaptureIntent(), ConstKeys.SCREEN_RECORD_REQUEST_CODE);
Log.e("RecordingLog","OnFinished");
} else if (isServiceRunning(RecorderService.class)) {
//stop recording if the service is already active and recording
}
finish();
}
};
}
//Create application directory
public static void createDir() {
File appDir = new File(Environment.getExternalStorageDirectory() + File.separator + ConstKeys.APPDIR);
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) && !appDir.isDirectory()) {
appDir.mkdirs();
}
}
private boolean isServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.e("RecordingLog","OnActivityResult");
//The user has denied permission for screen mirroring. Let's notify the user
if (resultCode == RESULT_CANCELED && requestCode == ConstKeys.SCREEN_RECORD_REQUEST_CODE) {
return;
}
Intent recorderService = new Intent(this, RecorderService.class);
recorderService.setAction(ConstKeys.SCREEN_RECORDING_START);
recorderService.putExtra(ConstKeys.RECORDER_INTENT_DATA, data);
recorderService.putExtra(ConstKeys.RECORDER_INTENT_RESULT, resultCode);
startService(recorderService);
Log.e("RecordingLog","Recorder Service");
}
}
How can i fix this?
onActivityResult called when the child activity is finished. In your case after you start an activity, you finish the RecordingActivity.
#Override
public void onFinish() {
if (mMediaProjection == null && !isServiceRunning(RecorderService.class)) {
//Request Screen recording permission
startActivityForResult(mProjectionManager.createScreenCaptureIntent(), ConstKeys.SCREEN_RECORD_REQUEST_CODE);
Log.e("RecordingLog","OnFinished");
} else if (isServiceRunning(RecorderService.class)) {
//stop recording if the service is already active and recording
}
finish(); // what does this method do?
}
I assume that finish method finished your activity. If it does so, onActivityResult will never be called because you finish parent activity.

Android background service stopped/paused on Huawei

I have developed an Android app that has a background service that runs endlessly and saves on a local SqLite DB the results of bluetooth scan and GPS positions. Only on Huawei devices this service seems to be paused or stopped for some minutes (I noticed that after inserting some log into the code): in theese minutes any log is written.
. I tried without success to change some settings of device (battery optimization).
Do you have some advice to solve the problem?
Below you can find a snipped of the service.
public class MyService extends Service {
public MyService() {
super();
}
#Override
public void onCreate() {
super.onCreate();
...
...
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForeground(1031, getNotification());
}
final Intent serviceIntent = new Intent(getApplicationContext(), MyService.class);
ServiceConnection connection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className, IBinder service) {
MyServiceBinder binder = (MyServiceBinder) service;
started = true;
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
started = false;
}
};
bindService(serviceIntent, connection, Context.BIND_AUTO_CREATE);
}
#RequiresApi(Build.VERSION_CODES.O)
private Notification getNotification() {
NotificationChannel channel = new NotificationChannel("channel_01", "My Channel", NotificationManager.IMPORTANCE_DEFAULT);
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
Notification.Builder builder = new Notification.Builder(getApplicationContext(), "channel_01");
builder.setContentTitle(getString(R.string.app_name))
.setAutoCancel(true)
.setColor(getResources().getColor(R.color.colorAccent))
.setContentText(getString(R.string.app_name))
.setSmallIcon(R.drawable.ic_stat_onesignal_default);
return builder.build();
}
public class MyServiceBinder extends Binder {
MyService getService() {
return MyService.this;
}
}
private void stopForegroundService()
{
// Stop foreground service and remove the notification.
stopForeground(true);
// Stop the foreground service.
stopSelf();
}
#Override
public void onDestroy() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
stopForegroundService();
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//Restart after 5 secs
Handler h = new Handler(Looper.getMainLooper());
h.postDelayed(new Runnable() {
#Override
public void run() {
GenericUtility.launchService(MyService.class, getApplication());
}
}, 5000);
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
...
...
initScanLoop();
initLocationManager();
return Service.START_STICKY;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return new MyServiceBinder();
}
#Override
public boolean onUnbind(Intent intent) {
boolean res = super.onUnbind(intent);
return res;
}
/*Init bluetooth handler*/
private void initScanLoop() {
final Handler h = new Handler(Looper.getMainLooper());
h.post(new Runnable() {
#Override
public void run() {
scanLeDevice();
hBeacon.postDelayed(this, SCAN_DURATION + 10000);
}
});
}
private void scanLeDevice() {
if(mLEScanner != null && !scanning.get() && !stopScan) {
scanning.set(true);
mLEScanner.startScan(null, settings, mScanCallback);
Handler mHandler = new Handler(Looper.getMainLooper());
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
if(scanning.get()) {
stopScanLeDevice();
}
}
}, SCAN_DURATION);
}
}
private void stopScanLeDevice() {
scanning.set(false);
if(mLEScanner != null) {
mLEScanner.stopScan(mScanCallback);
}
}
/*Finish bluetooth handler*/
/*Init GPS handler*/
private void initLocationManager() {
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
createLocationChangedCallback();
locationListener = new BeaconScanLocationListener(locationChangedCallback);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
}
private void createLocationChangedCallback() {
locationChangedCallback = new LocationChangedCallback() {
#Override
public void callback(final Location location) {
try {
//GPS callcback
} catch(Exception e) {
}
}
#Override
public void enabledDisabled(boolean enabled) {
}
};
}
/*Finish GPS handler*/
}
UPDATE
I improved app functionality replacing bluetooth scanning with monitoring beacon in region function of Android Beacon Library.
You have to configure in settings for app can run in background for Huawei
you can check out this link here
This problem can you fix it by put your device in App launch normally the app manage by Huawei but you must make it manage manually after that Huawei can't put the service in sleep mode.

Categories