My app has a UI and a connection is made to a bluetooth device which is periodically sending barcode scan data to my app. I then want to cache this data in a sqlite db and have another process push this data up to a web server.
I have managed to get the UI and bluetooth scan process separated by using an Intent Service for the scanner component... The thread in the intent service connects to the bluetooth device and loops endlessly pulling in new scan data as it comes... communicating with the UI via broadcast messages as it needs to.
So now I need to handle storing the data in a sqlite db and pushing it up to the Internet.
I'm thinking I can insert a db row directly in the intent service loop I already have working for the bluetooth data... would I do that by firing of an async task or something like that?
Then, would I have a completely different intent service running and looping endlessly checking for new records to be processed and pushed up to my web server via an http post?
I guess the main reason I'm thinking of using intent services is that they seem to keep running even if I lock my phone and put it in my pocket... has worked so far for the bluetooth barcode scanner... can scan away happily with my phone locked and in my pocket.
I also need to handle the reality that internet won't always be available... hence the sqlite db... kind of like a safe buffer to store data until it can eventually be pushed up to the Web server.
Am I going down the right path? I'm really new to Android development and even after much research I'm still unsure about my approach.
You can store data or communicate from IntentService onHandleIntent() directly. You don't need to run it in separate thread, unless you want reading bluetooth to continue ASAP.
Handling everything in an infinite loop smells. Also keeping service alive depends on few factors. If IntentService dies, it won't be restored because by default IntentService.onStartCommand implicitly returns START_NOT_STICKY, or START_REDELIVER_INTENT if you call setIntentRedelivery(true) on this service. Check Service javadoc for more info.
If you can scan bluetooth periodically then I would consider kind of scheduler. For that you would probably need to implement Service, not IntentService and handle background thread yourself. Alternatively, you could use a Timer. These are more hints, not ready solution. Since you asked about direction, I assume you will investigate solutions yourself.
Depending on handled data you could separate DB operations and network to separate services. Think about them as modules which are decoupled. You will benefit maintaing this code in the future and in case one service goes down due to any reason, the rest will keep working. It depends on data size because it's not a good practise to push heavy data between service/activities(data is serialised and deserialised every time it is sent).
If DB is just a buffer/queue then maybe use it directly after reading bluetooth data. In other words queue data for sending. Create second service for HTTP communications. Don't push entire data to second service, just inform it about(knock the door :)) and let HTTP service access DB by itself. I would wrap DB in ContentProvider and access it from services.
There are probably different techniques out there too, but that's what I thought about it in the first place.
Related
I am collecting data from different activity and sending to the server periodically, also if the user is in offline mode am using Sqlite to save data and again sending that whenever the internet available,
I have to schedule this transmission from many activities
which is the best for my requirement asyncTask or IntentService ?
I have to divide the data as chunks if huge data present in Sqlite, please suggest some algorithms to do this.
1.asyncTask is used lock the ui thread and ruining for long time process such as connect the web server.more details
2.IntentService is one kind of service it use handle asynchronous requests.more details
you can see this tutorial for send data to web server sync
Intent service is the best method, also it avoids context leak !
There are couple of things that are bugging me in the process of downloading data and notifying the UI in Android. I'm using (Intent)Services to download the data, which works good enough.
I'm not sure how to deal with notifying the UI that data has been retrieved though. After some research and discussion in Downloading data using IntentService - Lifecycle Changes, and Which is the best way to communicate between service and activity?, I'm arriving at a point where I'm not sure which method to use anymore.
The alternatives I'm looking at are:
Service + LocalBroadcasts + Databases
An Activity would start the Service
The Service would download the data into a database
The Service would send out the Broadcast with a 'done' notification
The Activity would pick up this Broadcast and retrieve the data from the database using an AsyncTask
The Activity would retrieve the data from the database using an AsyncTask every time it is shown to the user (onResume, for cases it has missed the broadcast due to the user navigating away).
Service + ResultReceivers + Databases
An Activity would start the Service
The Service would download the data into a database
The Service would notify the ResultReceiver that it's done
The Activity would retrieve the data from the database using an AsyncTask
Instead of retrieving the data every time, the ResultReceiver is reused across lifecycle changes, and notifications are not lost.
Service + ResultReceivers + Bundle
An Activity would start the Service
The Service would download the data (optionally into a database)
The Service would notify the ResultReceiver that it's done, and supplies the data in a Bundle.
The Activity would retrieve the data from the Bundle (No AsyncTask needed).
Instead of retrieving the data every time, the ResultReceiver is reused across lifecycle changes, and notifications are not lost.
Options 1 and 2 require the user waiting for the database read/write operations. Option 3 is therefore quicker, but I've seen many sources recommend not using Broadcasts or ResultReceivers to transfer data (I'm not sure exactly why though).
For now, I am sticking with option 3, but I'm not sure if this is actually a proper approach, and if I'm missing something.
Can someone shed some light on this?
While some people (possibly righteously) vote this question to be opinion based, I am looking for pitfalls I am possibly overlooking. Furthermore, I'm looking for the answer as to why using ResultReceivers or Broadcasts for sending result data is recommended against.
Carefully using some sort of DataManager singleton instance, backed up by a database seems to be a robust solution. Using ResultReceivers, the UI gets notified and pulls the data from the DataManager.
I have also found out that using ResultReceivers and Broadcasts to send data has a negative impact on performance, because the objects need to be serialized. This is a costly operation, and GC might kick in because of it.
I have an application that uses a webservice to get information and save the changes made by the user.
currently I have one service that runs while the application is open, and it has public methods for each operation. the trouble is that service is growing considerably and I'm thinking refactor, but the question is what is the best way?
I can think of the following options:
Deferred services the current service and that all are initialized at boot time application
Create small services and that these are initialized by local broadcast
although I have doubts about performance. Can give me some clue or example about which method is better, do not really care that changes are instantly synchronized, these are stored locally and can be synchronized when possible. Data sent are not many, so the synchronization is relatively fast
Synchronization processes are something like
Check if there is new data (I have several types of data, these are the ones that are growing)
Synchronize user preferences
Most likely there's no point of having Service running all the time. Instead, I'd go for IntentService. If possible, I'd also condifer using push notification (like GCM) so the server could let my app know that there's new data to fetch (or maybe even send it to me if you'd fit in the GCM payload limit).
I am in the process of making an application. I currently have a database and a method that uploads pictures (along with data corresponding with the picture/s, stored in the database) using a PHP script on the server. Neither the purpose nor the database's schema are important. I haven't really done anything like this before but have looked into it a bit. Basically the user will take a picture with the app. The picture and its data will upload if there is a network connection, but won't if there is no connection (duh). I want to have the pending images upload once a connection exists.
To do this...My current plans are to use a BroadcastReceiver to detect when the user is connected to a network then use a Service to upload the files. Is this the proper approach? How can I basically go about starting a service when connectivity exists if and only if there are pending uploads?
Your approach sounds reasonable to me in general.
You would register a broadcast receiver with your package, listening for android.net.conn.CONNECTIVITY_CHANGE.
If the activities also trigger your service, you may be able to properly handle every case with an IntentService alone, so you won't have to deal with the many questions around when to stop or start a service with a specific life cycle.
Hope this helps; you don't sound like a beginner so you'll be able to make ends meet.
I've asked various questions related to one goal: how to develop an Android app that plots bluetooth data forever in real-time. I now have a new question from a different angle. To be fair to new readers I will cover some of the same background, but basically the question is in the title.
I found some open source code Bluetooth that apparently creates a background thread which updates the screen with new data it receives over a bluetooth connection. Then when I launch my Plot activity I can see the bluetooth background thread continue to write bluetooth data to Logcat. So I know for a fact the bluetooth background thread is still running when I launch my Plot activity.
Again, my goal is to plot the bluetooth data that is continually provided by the bluetooth background thread. I have succeeded as follows: since this bluetooth background thread seems to run continually and just won't die, I decided to use its update() method to call my static Plot.plotData() method to plot the data. And this works. It will will run endlessly with out a problem - receiving bluetooth data and plotting it via periodic calls from the bluetooth background method update() to my static Plot.plotData() method.
Although I have received some negative feedback regarding my solution, I have found sharing data across Activities where Edward Falk says sharing static data is OK. Here Edward Falk asks: "Are the activities all in the same application? [yes] Same task? [not sure] It seems to me that you could just store the data in a static variable accessible by all of the activities." Well I tried static data and it worked, but I switched to a static method Plot.plotData() which seems to work better for me.
The latest feedback I have received from one person #emmby that says my static Plot.plotData() goes against the following: "It sounds like you're looking for an in-memory way to share data, and that's simply not the way the Android activity model works." But what am I else to do? I thought that an Android phone has a limited amount of RAM for running Activities (one at a time), threads, handlers, Services, AnycTasks, etc. And an SD card for persisting data.
#emmby seem to say that in order to share data from a bluetooth background thread to my Plot activity (Plot.plotData()) that I must use the SD card. This doesn't sound right. After all I have it working using my static method Plot.plotData().
Frankly I don't see anything wrong with my solution primary because those who criticize it do not follow up with a definitive alternative.
If you find my solution deficient please speak up and provide a definitive solution. Otherwise I will take Edward Faulk's solution as the best one.
If I understood you correctly, your thread is running at the background even when none of the activities display data obtained by that thread. For example, let's consider scenario:
You started your bluetooth thread.
Your activity A started and now read data from that thread.
Your activity A is backgrounded (for example user navigates away via "Recent" tasks).
Your activity is idle but bluetooth thread still consumes cpu and power.
If you don't use your bluetooth data you shouldn't run the thread. You can introduce some kind of counter that tracks number of clients that use your thread's data. And if counter drops to zero - thread stops/pauses.
But Android has built-in solution for such cases. You can introduce service which will be bound by different activities and will have DataSource interface with getNextData function. See Bounded Services for more details.
When there are no clients bound to service Android will stop the service. This way you completely decouple Activities from thread. Your bluetooth thread is now managed by Service. And Service is now managed by Android.
In your case Local Service should be enough to share data between your thread and activities.