job scheduler not working in xiaomi android - java

The Job Schedular set as follows
ComponentName mServiceComponent = new ComponentName(context, TestJobService.class);
JobInfo.Builder builder = new JobInfo.Builder(jobId, mServiceComponent);
builder.setPeriodic(3 * 60 * 1000);
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_NONE);
builder.setRequiresDeviceIdle(false);
builder.setRequiresCharging(false);
builder.setPersisted(true);
JobScheduler jobScheduler = (JobScheduler) ChaseForceApplication.getAppContext().getSystemService(Context.JOB_SCHEDULER_SERVICE);
jobScheduler.schedule(builder.build());
The TestJobService class is like this:
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class TestJobService extends JobService {
#Override
public boolean onStartJob(JobParameters params) {
Utility.writeToTheFile(ChaseForceApplication.getAppContext(), "\n\n Job Scheduler StartJob with jobid="+params.getJobId()+" set at " + new Date().toString());
sendBroadcast(new Intent(this, OnSingleAlarmReceiver.class));
return false;
}
#Override
public boolean onStopJob(JobParameters params) {
Log.i(ChaseForceApplication.TAG, "on stop job: " + params.getJobId());
Utility.writeToTheFile(this, "on stop job: " + new Date().toString());
return false;
}
}
It's working on most devices, even in other xiaomi phones but in Xiaomi Redmi 3S it is not working.
Is any setting required for Job Schedular to make it work on that device?

It seems that Xiaomi MIUI operative system don't allow JobScheduler to run https://web.archive.org/web/20171001070316/http://c.mi.com/thread-8779-1-1.html

From your app settings/info page, try to enable auto start and then retry with job scheduler. It will work. You need to enable autostart for your app.

Related

JobService stopping by battery save mode and 15% - 10% - 5% status

I'm using a JobService to keep my notifications running even when app is closed by the user, but when cellphone goes to battery save mode or 15%, my service stop to work.
I would like to understand if exists a way to avoid it, thanks
TelaPrincipal.java
public class TelaPrincipal extends AppCompatActivity {
cancelarJob();
startarJob();
[...]
}
public void cancelarJob(){
JobScheduler scheduler = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);
scheduler.cancel(123);
Log.d(TAG, "Job cancelled");
}
public void startarJob(){
ComponentName componentName = new ComponentName(this, ExampleJobService.class);
JobInfo info = new JobInfo.Builder(123, componentName)
.setRequiresCharging(false)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
.setPersisted(true)
.setPeriodic(15 * 60 * 1000)
.build();
JobScheduler scheduler = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);
int resultCode = scheduler.schedule(info);
if (resultCode == JobScheduler.RESULT_SUCCESS) {
Log.d(TAG, "Job scheduled");
} else {
Log.d(TAG, "Job scheduling failed");
}
}
You don't need any type of service of job to keep a notification around. Notifications stay until the user swipes them away. But no, there is no way to force this- when the battery is low, the OS kills everything it can to minimize power usage. Which is the right choice- the user will almost certainly prefer to miss your notification than have his phone die on him (although again, you don't need anything like this to keep a notification around)

Vaadin why not show notification in multiThreads app

My problem is that in my app not show notification.
My application does that each time a button is pressed I create new thread and show notification with info that thread is running or waiting (this works fine). Then, if the thread is running, it will randomly sleep for 5-10 seconds and get data from the rest api and a notification should be displayed that the thread is finished (this notification is not displayed).
Fineshed notifications show after i press again button. As you can see in the image.
Image:
constructor view:
public MainView() {
Button ipButton = getIpButton();
setMargin(true);
setHorizontalComponentAlignment(Alignment.START, ipButton);
add(ipButton);
}
button:
private Button getIpButton() {
final UI ui = UI.getCurrent();
final VaadinSession session = VaadinSession.getCurrent();
Button ipButton = new Button("My IP");
AtomicInteger orderIndex = new AtomicInteger();
ipButton.addClickListener(_e -> {
int orderThread = orderIndex.getAndIncrement();
openBeginNotification(orderThread);
executor.submit(() -> {
try {
UI.setCurrent(ui);
VaadinSession.setCurrent(session);
long sleepTime = (long) (Math.random() * (10 - 5) + 5);
System.out.printf("%d: %ds\n", orderThread, sleepTime);
Thread.sleep(sleepTime * 1000);
IpDTO ip = restTemplate.getForObject("http://ip.jsontest.com/", IpDTO.class);
System.out.printf("%d: %s\n", orderThread, ip);
try {
VaadinSession.getCurrent().lock();
getFinishNotification(orderThread).open(); // here not show notification
VaadinSession.getCurrent().unlock();
} catch (Exception e) {
e.printStackTrace();
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});
});
return ipButton;
}
notification methods:
private void openBeginNotification(int orderThread) {
Notification notification;
if (executor.getActiveCount() == MAX_THREADS) {
// thread is in front
notification = getWaitNotification(orderThread);
} else {
// thread run
notification = getRunNotification(orderThread);
}
notification.open();
}
private Notification getRunNotification(int orderThread) {
return getNotification("Task " + orderThread + ": run", NotificationVariant.LUMO_PRIMARY);
}
private Notification getWaitNotification(int orderThread) {
return getNotification("Task " + orderThread + ": wait", NotificationVariant.LUMO_CONTRAST);
}
private Notification getFinishNotification(int orderThread) {
return getNotification("Task " + orderThread + ": finish", NotificationVariant.LUMO_SUCCESS);
}
private Notification getNotification(String notificationText, NotificationVariant variant) {
Notification notification = new Notification(notificationText, 1000);
notification.addThemeVariants(variant);
return notification;
}
First, you need to enable #Push to make Vaadin open a websocket connection that makes it possible for the server to directly send messages to the browser without waiting for the browser to send a message asking for changes (which happens when you click a button). The #Push annotation should be in different location depending on the Vaadin version you're using, so please refer to documentation to find the right place.
Second, please use UI::access instead of manually doing setCurrent and locking. While I didn't spot anything in your example that would break the happy case, there are still also a whole bunch of edge cases that you'd need to take into account. As an example, you're not cleaning up after setCurrent which might cause memory leaks and you're not unlocking in case something related to the notification throws an exception.

Scanning for Bluetooth LE devices when the phone is in doze mode, don't work. CallBack method dosn't called when doze mode

I am developing an Android app (the app runs on Android 6): I want the app to send a notification to the user when it is near a BLE device (a device that I have at home). So I continuously scan, I scan through a service (which is running in the background). It works well when the phone screen is on; but, when the screen turns off, a few seconds later the application can no longer find the BLE (the scan is still running, but there is no callback.
if (enable) {
if (mScanning) return;
// Stops scanning after a pre-defined scan period.
handler.postDelayed(new Runnable() {
#Override
public void run() {
if (!mScanning) return;
try {
mScanning = false;
mBluetoothLeScanner.stopScan(mScanCallback);
Log.i(TAG_LOG, "Stop scanning after pre-defined scan periode");
} catch (Exception e){Log.e(TAG_LOG,"mBluetoothLeScanner.stopScan Exception:=>"+e.getMessage());}
}
}, SCAN_PERIOD);
mScanning = true;
mBluetoothLeScanner.startScan(filters, settings, mScanCallback);
Log.i(TAG_LOG, "Start scanning ....");
}
private ScanCallback mScanCallback = new ScanCallback() {
//When a BLE advertisement has been found
#Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
Log.i(TAG_LOG, "Name: "+result.getDevice().getName()+". Adresse: "+result.getDevice().getAddress()+". Rssi: "+result.getRssi());
//scanDevices(false);
if(result.getDevice().getName() != null && result.getDevice().getName().toString().equals(deviceName)){
mDeviceAdress = result.getDevice().getAddress();
mDevice = mBluetoothAdapter.getRemoteDevice(mDeviceAdress);
Log.i(TAG_LOG, "Device found");
scanDevices(false);
}
}
You can't make this work. Scanning is a very expensive operation that Android won't allow in the background. Instead, make an attempt to connect to the device. I had success doing this in a WorkManager job, running every 15 minutes. Battery drain was negligible and it was pretty reliable. Note that a connection state 0x85 usually represents the device being out of range, and 0x80 means a different device is already connected to it (or the phone is already connected to too many different devices). Full error list is at https://android.googlesource.com/platform/external/bluetooth/bluedroid/+/master/stack/include/gatt_api.h#27

How to know if a specific app comes to foreground?

Check if an app, for example, Instagram is started by user.
Note: My app is targeting lollipop and above versions in android
Yeah the only way you can do it is through the Accessibility Service. Look at this page to understand how to create it. https://developer.android.com/training/accessibility/service.html They will also need to enable the service via the services -> accessibility screen.
AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED you can probably interrogate the package in front to figure out if Instigram is on top.
You definitely don't want to use getRunningTasks since the function was modified in Android 5.0+
I figured out that I can do this by using usage access feature.
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static String getForegroundProcess(Context context) {
String topPackageName = null;
UsageStatsManager usage = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
long time = System.currentTimeMillis();
List<UsageStats> stats = usage.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000*1000, time);
if (stats != null) {
SortedMap<Long, UsageStats> runningTask = new TreeMap<Long,UsageStats>();
for (UsageStats usageStats : stats) {
runningTask.put(usageStats.getLastTimeUsed(), usageStats);
}
if (runningTask.isEmpty()) {
return null;
}
topPackageName = runningTask.get(runningTask.lastKey()).getPackageName();
}
if(topPackageName==null) {
Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
context.startActivity(intent);
}
return topPackageName;
}
Now continuously check if the desired app is in the foreground.
String fg=getForegroundProcess(getApplicationContext());
if(fg != null && fg.contains("com.instagram.android")){
//Instagram is in foreground
}else {
}
I continuously run the above code with a job service.Which is available for
lollipop and above.

Sending DataMap in a background service android

I'm trying to send the content of a DataMap from an Android device to a wearable. It works fine when the app is in the foreground on my app but once I lock the mobile device it gets stuck at the pendingResult.await() and the wearable doesn't receive any data where as it normal would if I keep the app open.
public void send(final DataMap dataMap) {
new Thread(new Runnable() {
#Override
public void run() {
PutDataMapRequest putDMR = PutDataMapRequest.create(WEARABLE_DATA_PATH);
putDMR.getDataMap().putAll(dataMap);
PendingResult<DataApi.DataItemResult> pendingResult = Wearable.DataApi.putDataItem(googleClient, request);
DataApi.DataItemResult result = pendingResult.await();
if(result.getStatus().isSuccess()) {
Log.d("qwe", "Data item set: " + result.getDataItem().getUri());
}
}
}).start();
}
This method is in a class which extends WearableListenerService and I have added the XML in the AndroidMainfest for the service also. Am I doing something completely wrong or missing something?
Thanks
try to check google api client status for each send.
use blockingConnect when google api client is not connected.
Found out I was doing googleClient.disconnect() in my main activity onStop() which was causing it to hang as googleClient wasn't connected once my app was in the background.

Categories