I'm building an app that will read sensor data and store it into kafka with rest controller as middleman. (First time working with sensors)
UI consists of Sensor name + switch button to start or stop sending sensor data.
I'm trying to regulate how much of sensor data is send, because my android app just cant keep up with some of the sensors when they start with sending data, my UI just blocks.
I was testing with Emulator and sensors that have goldfish in there name, they work normally, Game rotation vector sensor, gravity sensor, and few others just start sending to much of data and app cant keep up.
(I'm sending data with new thread each time).
SensorManager.registerListener(sensorEventListener,sensor,500000000);
Changing samplingPeriod just didnt help at all, some sensors work normally and some just keep sending to much of data regardless of number.
I tried that, with each sensor change event, new Thread starts with sending data, so that UI would work normally, but my app cant keep up with some of the sensors.
public void onSensorChanged(SensorEvent sensorEvent) {
Thread t = new Thread(new MyOwnRunnableClass(sensorEvent,username));
t.start();
}
Make a native app to learn sensor
Don't create a thread every time a sensor updates because every thread generates over head. You want one thread to manage the sensors, one for ui. Should be enough.
Your sensor thread can drop readings if there are too many for your need (just process one out of ten)
Sampling rate used to work more or less when I used to develop in android native.
Read tutorials, using sensors is key in mobile so every framework has tutorials on how to do it the right way
Good luck
second way:
you can set previous time in shared preferences and in OnSensorChanged method check if difference of current time and last time is over than 500000 set your data.
first way:
you can use alarm manager to do this every 500000 s;
Related
The PeriodicTimeRequest has a minimum periodic time of 15 minutes. But I see, that for example Google Maps location sharing can update more frequently than that, and facebook messenger can also receive messages almost instantly.
I would like to send a notification to the user, when it got a new message. My application has to work on local network, so Firebase is not an option. I have to send a json request to the server, and if there is a new message, I show a notification to the user.
Regarding FCM:
FCM, which is available in all devices with Google Play takes the weight of subscribing to and receiving push events, under all the resource constraints Android has been ever introducing.
It's tightly coupled with the OS and is unified (one entity, one persistent connection for all apps in your device), which is why it works :)
Regarding Frequency of your Work:
Given your requirement of more frequent pings to the server, you'd need to have a service which runs all the time, i.e. A Foreground Service.
It is resource consuming though, so good luck convincing the user with a good reason why it should stay alive all the time.
I think you've managed to make the client-server interaction possible, since identifying a server in a local network is a huge task in itself.
use this in your service.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
CountDownTimer timer = new CountDownTimer(15 * 60 * 1000, 1000) {
#Override
public void onTick(long millisUntilFinished) {
// execute your task here, every sec
//if you want increase the count down interval from 1000 to what you want
}
#Override
public void onFinish() {
this.start();
// it will start again.
}
};
timer.start();
return START_STICKY;
}
I am afraid it is not going to be possible without using a set of workarounds. Which means you might not get a consistent behavior.
#Arvind has done a very good job explaining the benefits of a Firebase Service and it is the recommended approach for achieving such task.
First I'd like to point out that such restrictions on the WorkManager exist because Android has been suffering (between other things) of developers trying to abuse some mechanisms to get their software working and at the end of the day, the battery of the users had been suffering from such abuses and since Android 6 Google has started trying to address these issues. There's a good read for you over here about Doze mode and how to work with it
I am pointing this stuff out because I've been trying to build a chat service that wouldn't rely on Firebase and I really don't want you to waste as much time as me banging your head against a wall. There are things that you simply can't fight. That means that if the device enters in a "deep-sleep" mode sometimes you can only accept it.
My approach
Please
keep in mind the user interests and the life of their batteries and try to be as smooth as you can with their devices and this is just a workaround over the restrictions that have been imposed upon us. And that I discourage this approach due to the amount of work that it takes to pull off and for how misused it can be.
My solution
Essentially, to get notified (ie getting your code running) in an Android App you're going to be wanting to receive system events or Broadcasts. This is where you set up a BroadcastReceiver and you get Intents delivered to it and you can act upon them accordingly. BUT YOU HAVE TO BE QUICK BECAUSE YOU HAVE ONLY 10 SECONDS OF RUNTIME BEFORE THE OS KILLS THE PROCESS AGAIN. Ideally you would have a really quick server so you can have very little IO times to ensure you can be within 10 second restriction as frequently as possible.
So essentially you would be using a combination various of services that you would like to be monitoring in order to get notifications (aka Broadcasts) whenever the state of those changes. Here are a few ideas:
WiFi state (which will also be useful to see if you can reach your local server)
Bluetooth Low Energy packets (or Nearby which may solve the entirety of your problem depending on Nearby's capabilities)
WorkManager as you already pointed out.
AlarmManager to schedule a broadcast of intents every so often.
Geofencing (although it involves reading the user's location; you can set really small geofences around the office building and get notified by a Broadacast when users go through that geofence)
So whenever you receive a Broadcast of these sources you would handle such notifications from within the same BroadcastReceiver
From the implementation body of this Broadcast receiver you would poll the local network's server to check whether if your user has new messages or not and lift up a notification. And it's important to keep the amount of work and IO times the app has to do at a minimum since those add up and you've got only 10 seconds.
You can get around the 10 second mark if you launch a ForegroundService. Then, that period of time is going to be extended until a 10 minute mark and you will need a visible notification for the user stating something that you're checking if it's got any new messages.
Keep in mind
Don't stress the user's battery too much. Or Android will penalise your app and you'll end up notified less often or even completely not notified.
Be gentle with the user. If the user has to force-kill your app at some point it will stop receiving any sort of Broadcasts or running any sort of WorkTasks.
This solution can behave differently accross devices. Since the decisions of notifying your app are made by the OS, different OS (redmi, samsung, meizu...) you are likely to not end up with a consistent behavior across all devices
You don't have control over things, the OS does
Within measure, try to time your Broadcasts to your BroadcastReceiver within spans of 3 minutes or so; so you are always receiving a Broadcast below the 15 minute mark.
I'm reading Sensor Data from Device Sensors(Multiple Sensors) and call a Method to show the data I received from sensors to the designed TextView.
The method I'm calling to update TextView:
private void UpdateDataStream(String _Entry,Boolean isAppend)
{
if(isAppend)
ViewHolder.append("\n("+sensorName+")"+_Entry);
else
ViewHolder.setText("("+sensorName+")"+_Entry);
}
Method called from SensorEventListener's , onSensorChanged Event.
What I couldn't figure out is how to prevent freeze while updating TextView; since sensor data update is intensive(considering it is from multiple sensors simultaneously) updating TextView cause Application to freeze or crash. I don't need to "print" every data I received, like It is enough for me to print for every 1-2 second, lost data can be ignored.
Is there any approach/patern or built-in structure to achieve this ?
(I'm new to programming in Java&Android, yet I'm familiar with multiprogramming, parallel programming concepts, yet I couldn't figure out how to apply them in this environment)
This is fastest solution:
https://github.com/ReactiveX/RxJava
http://reactivex.io/documentation/operators/debounce.html
Or you can:
create stack (for example)
write sensors data stream to stack from thread#1
in another infinite loop thread#2 read last data from stack every N time (don't forget to synchronize them)
clean the stack
write last data to TextView (don't forget to set text in ui thread: textView.post( () -> textView.setText("safe call") );
I have been developing an Android app to track eating throughout the day. We have not decided on which sensors to use yet, so the app is capable of connecting to all of the sensors from a Service and streaming them for an indefinite amount of time, depending on when the phone decides to clean up the app's resources. What I have noticed during reliability testing is that accelerometer and gyroscope cut out after two to three minutes when they are both streaming at medium or high frequency. I have implemented a timeout thread that checks for the last received accel or gyro data (depending on if they are supposed to be streaming) and re-registers new listeners if they stopped streaming. Is anyone else having this issue and/or does anyone have recommendations for a less battery intensive way of reliable acc/gyro streaming?
To summarize:
Registered accelerometer and gyroscope listeners stop receiving data after 2-3 minutes
This only happens when streaming accel/gyro at the medium and high frequency settings and only when accel and gyro are both streaming
This happens regardless of whether other sensors are streaming or not
No exception is thrown when this happens
Subscription/unsubscription as well as incoming data are all handled on new threads
I have a hacky timeout thread that unregisters and registers new listeners for accel/gyro if they stop streaming
Questions:
Is anyone else running into this issue?
Is there an issue with using new Threads to handle the data that would be causing the listeners to be unregistered (unlikely because other data works implemented this way)?
Is there a better (more battery efficient) way of detecting an event not occurring and responding to that than having a thread check for a timeout?
Thanks in advance!
Four things.
1) The Microsoft Band gyro sensor data on the SDK includes the accelerometer data, so you should never need to subscribe to both at the same time.
2) Subscribing to either over a long time will drastically drain the battery life of whatever band is being connected to and is thus not advised.
3) Streaming requires that a connection to Microsoft Health's BandService remains active. And if that connection is lost, you will no longer get data. (Likely this is what is happening in your case)
4) Microsoft has a cloud API that might be more useful for what you want to do. http://developer.microsoftband.com/cloudAPI
Do you have any other devices connected to your phone via Bluetooth? If so, try disconnecting everything except the Band.
From my experience, having another device paired and communicating with the phone causes the listeners to shut out without notice, often requiring a restart of the app or the phone. My phone was collecting data from a tablet and the sensors at the same time, and I discovered that the sensors would last more than 2-3 minutes if I didn't connect to the tablet at all.
Hope this helps!
For my app, I have about 15Mb (which can be compressed with some processing power to about 5Mb) of audio+video+image data that I need to save to disk. For instance, I need to save this when user is interrupted with a phone call (because the activity might get killed after this) and when the user leaves the app.
I can save the data to SD card in about 10 seconds if I don't compress it and something like 20 seconds if I do compress it, where I'd like it compressed. What options to I have for saving my data when onPause is called such that I can be sure the data has been saved?
From some basic experiments, my activity gets killed if onPause hasn't finished after 5 seconds. Some ideas I've had:
Starting a new Thread in onPause and saving the data there. This seems to work fine but seems like something I shouldn't be doing.
Starting a service, copying the data to the service somehow (would this be slow?) and then getting the service to save the data. I think this puts a notification icon at the top of the phone, but I don't think it's awful for a user to see the "Saving data..." task here.
Can I put the data in a SQL database quickly and then save it later when the user returns to the app?
(Due to the nature of the app, there really isn't any practical way I can save the data as I go because the user can transform the data in destructive ways with time consuming operations (e.g. 10 seconds for some operations). Even if I stored the original data and a list of the actions performed to recreate the data, the user would have to wait a minute or two when the app is next started up to process this.)
What options to I have for saving my data when onPause is called such that I can be sure the data has been saved?
Technically, what you want is impossible. There are no guarantees after onPause().
The best answer is what #Viktor Lannér suggested. To phrase it another way, don't wait until onPause() to need to do 10-20 seconds of I/O. Devise some mechanism to allow you to save incrementally as the user performs operations, as a fallback mechanism if nothing else. This is akin to how a database maintains a transaction log.
Starting a new Thread in onPause and saving the data there. This seems to work fine but seems like something I shouldn't be doing.
This is dangerous, because if the activity is closing (e.g., onDestroy() will be called momentarily), Android might terminate your process before your thread is completed.
Starting a service, copying the data to the service somehow (would this be slow?) and then getting the service to save the data. I think this puts a notification icon at the top of the phone, but I don't think it's awful for a user to see the "Saving data..." task here.
Make this be an IntentService, so it automatically shuts down when the work is complete. I wouldn't "copy the data to the service", but rather make the data centrally available, by a static data member if needed. This will not automatically put "a notification icon at the top of the phone", and for something of this duration, that is probably not needed.
Can I put the data in a SQL database quickly and then save it later when the user returns to the app?
Flash I/O is not faster for a SQL database than for anything else.
Due to the nature of the app, there really isn't any practical way I can save the data as I go because the user can transform the data in destructive ways with time consuming operations (e.g. 10 seconds for some operations
Then this probably isn't designed for a mobile platform. Consider whether this app is an appropriate use of the technology.
I have a slightly strange thing happening in my code atm, which I don't understand... I would much appreciate any input anyone may have.
So here's the issue:
In my main Activity I fire a Service, using an Intent, when a button is pressed on screen. The Service instantiates 22 Runnable objects each of which read data constantly from 22 separate flat files. The data is fed into a matrix of objects (64 x 64). In my main Activity I have another button which starts a new Activity to visualises the data in the matrix. So when I press it it accesses the data stored in the objects at the same time as the 22 threads are feeding data into them. It is my understanding this kind of operation is the main reason to use threads! However, when I start the new activity it seams to interrupt and/or kill the threads as they no longer print their Log.d messages to logcat...
Is it a case that I need to bind my Activity to my Service to access data that it is processing or are the thread independent of the Service as my common sense would tell me??!
Thanks in advance for any advice!