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.
Related
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");
}
}
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.
I built app to play audio from internet, I use service to play audio in background, the question is how to show loding dialog while media player is in preparing posision in service(background) hire my Code.
Activity
package com.uqifm.onlineradio;
.......
public class MainActivity extends AppCompatActivity {
Button b_play;
Boolean started = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
b_play = (Button) findViewById(R.id.b_play);
b_play.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(started){
started = false;
stopService(new Intent(MainActivity.this,MyService.class));
b_play.setText("PLAY");
}else{
started = true;
startService(new Intent(MainActivity.this,MyService.class));
b_play.setText("STOP");
}
}
});
}
#Override
protected void onDestroy() {
super.onDestroy();
stopService(new Intent(MainActivity.this,MyService.class));
}
}
Service
package com.uqifm.onlineradio;
....................
public class MyService extends Service {
MediaPlayer mediaPlayer;
String stream = "http://xxxxx:36365";
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
mediaPlayer.setDataSource(stream);
mediaPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mediaPlayer.start();
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
mediaPlayer.release();
}
}
Register broadcasts, Start a ProgressDialog before you start the service. Then wait for the broadcast. After the broadcast, hide the dialog. see example in this thread. Send data from Service back to my activity
Put a ProgressDialog in xml and set the visibility according to your requirement. Use interface for communicating with service.
You can use Broadcast or try EventBus which is much more easier. You can post an event from the service using EventBus and receive the the broadcast in MainActivity and update the progress dialogue.
Please follow the link.
Maybe something like this:
fun playAudio(audioUrl: String){
showProgressBar()
var mediaPlayer: MediaPlayer? = MediaPlayer().apply {
setAudioStreamType(AudioManager.STREAM_MUSIC)
setDataSource(audioUrl)
prepareAsync() // might take long! (for buffering, etc)
}
mediaPlayer?.setOnPreparedListener {
hideProgressBar()
it.start()
}
mediaPlayer?.setOnCompletionListener {
mediaPlayer.release()
}
}
I need to execute some tasks when my application is closed.
I have made a service for do this and tried many things, but i don't have the good result.
If someone have a tutorial or some path to follow, it would be great
This is my service:
public class TrackersImporter extends Service {
private static TrackersImporter instance;
private static long refreshDelay = 1; // Minutes
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
private boolean isInit = false;
public ArrayList<Tracker> trackers = new ArrayList<>();
public static TrackersImporter getInstance(){
if (instance == null)
instance = new TrackersImporter();
return instance;
}
#Override
public void onCreate() {
HandlerThread thread = new HandlerThread("TrackersImporter",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
Toast.makeText(this, "onStartCommand", Toast.LENGTH_SHORT).show();
Message message = mServiceHandler.obtainMessage();
message.arg1 = startId;
mServiceHandler.sendMessage(message);
} catch (Exception e) {
Log.w("TrackersImporter", e.getMessage());
}
return START_STICKY;
}
public void addTracker(Tracker tracker) {
trackers.add(tracker);
}
protected void showToast(final String msg){
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
}
});
}
// Object responsible for
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg) {
addTracker(Runkeeper.getInstance(MainActivity.getActivity()));
addTracker(Strava.getInstance(MainActivity.getActivity()));
startImport(MainActivity.getActivity().getBaseContext(), MainActivity.getActivity().getAppUser(), trackers);
stopSelf(msg.arg1);
}
/**
* Perform data imports.
* Imports are performed only 1 time.
* Additional calls to this method are equivalent to no-op.
* Call init() then performImport() for each TrackerImportable
* #param user user receiving the datas
*/
public void startImport(Context context, User user, ArrayList<Tracker> trackers) {
Context ctx = MainActivity.getActivity().getApplicationContext();
LocalDateTime now = new LocalDateTime();
if (Preferences.getPref(ctx, "tracker_import_date") == "")
Preferences.setPref(ctx, "tracker_import_date", now.toString());
LocalDateTime past = LocalDateTime.parse(Preferences.getPref(ctx, "tracker_import_date"));
long duration = new Duration(past.toDateTime(), now.toDateTime()).getStandardMinutes();
if (isInit)
return;
if (duration > refreshDelay) {
Preferences.setPref(ctx, "tracker_import_date", now.toString());
for (Tracker tracker : trackers) {
if (tracker.isEnabled() && Tracker.isUserEnabled(context, tracker.getName())) {
tracker.init();
tracker.performImport(user);
}
}
}
isInit = true;
}
}
}
This is my mainActivity
public class MainActivity extends BaseActivity {
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
if (ConnectivityUtil.isConnected(this.getApplicationContext())) {
initGoogleFit();
initTrackers(appUser);
}
}
private void initTrackers(User user) {
Intent trackersIntentService = new Intent(this, TrackersImporter.class);
trackersIntentService.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startService(trackersIntentService);
}
#Override
protected void onResume() {
...
if (ConnectivityUtil.isConnected(this.getApplicationContext())) {
initTrackers(appUser);
}
}
}
First Create one launcher Activity which is like your Main Activity.
In Activity "onCreate" Method you need to start Service and Do Some thing if you wont in Service "onStartCommand" Method.
public class MainActivity extends Activity {
ArrayList<Integer> list;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService(new Intent(MainActivity.this,TrackersImporter.class);
}
public class TrackersImporter extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// do something
Log.v(TAG ,"Service is started");
}
}
And also Register this Service at manifest.xml like this.
<service android:name=".TrackersImporter"></service>
if you like stop service
stopService(new Intent(MainActivity.this,TrackersImporter.class);
I got 3 activities ( A , B ,C ) and a service that I call to check if I got new messages from DB. It's a HTTP request . I need to make the request each 15 sec.
Thread t = new Thread() {
#Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(15000);
runOnUiThread(new Runnable() {
#Override
public void run() {
// Here i call
}
});
}
} catch (InterruptedException e) {
}
}
};
t.start();
How to make it work when i am changing activities ?
Option: Consider changing setup to have three fragments as your original activities, and a MainActivity that controls the repeat polling for messages to DB, as well as controlling the fragments.
#SuppressLint("SimpleDateFormat")
public class AlarmService extends Service {
private PendingIntent pendingIntent;
Handler mHandler;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
}
public void f() {
Toast t = Toast.makeText(this, "Service is still running",
Toast.LENGTH_SHORT);
t.show();
};
}
#Override
#Deprecated
public void onStart(Intent intent, int startId) {
Toast t = Toast.makeText(this, "Service started", Toast.LENGTH_SHORT);
t.show();
// TODO Auto-generated method stub
super.onStart(intent, startId);
mHandler = new Handler();
Runnable r = new Runnable() {
#Override
public void run() {
f();
mHandler.postDelayed(this, 20000);
}
};
mHandler.postDelayed(r, 20000);
}
}
and in manifest use this
<service android:name="com.example.yourservice"></service>