My Android app needs to be constantly receiving via USB serial in the background of my app, while sending information via USB serial only happens on certain functions. When we send and receive I am always sending a packet of X bytes every time. I understand how Android USB API works, the thing that I am having trouble with is how would I organize this? Would I use a thread for receiving only and the rest as functions, or for the whole USB connection/sending and receiving all together is in a thread? The main activity is called "Homescreen.java" and here is how I have it organized so far.
public class HomeScreen extends Activity implements OnTouchListener, Runnable{
onCreate() { }
onResume() { }
onStart() { }
onDestroy() { }
run() { }
}
Note: The reason there is no onPause is because this app is a fullscreen widget and should never be closed.
Another question: If I was to make a thread would I have to make it extend from Homescreen.java? And what of Context? Can I just import it? (Not very keen on Context object)
this is more of design choice, for instance if you want one background thread to handle the data from USB
public class test extends Activity{
Thread t;
runT= true;
public void onCreate(Bundle b)
{
..........
..........
t = new Thread(new Runnable() {
#Override
public void run()
{
while(runT)
{
//call data read or send functions here you can add condtion to sleep the thread as well
}
}
});
t.start();
}
}
When you are ending the activity simply set runT to false, which will stop the thread.
You can also have a thread pool and use theads accordingly.
If this is not happening frequently you can start an Asynctask everytime you want to send data.
You can look at AsyncTask. It is a special thread implementation for Android that should keep things simpler. If you are not doing any threaded "heavy lifting" I would recommend going with AsyncTask. You simply write an inner class inside your HomeScreen class, write your logic and call it from your Activity (for example from within onCreate()).
You could try getBaseContext() from within the Activity - I guess this will get you the relevant Context.
Cheers
Related
I've created a nested class within my Activity
public class MissionsActivity extends Activity {
class UpdateMissions implements Runnable {
#Override
public void run() {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
[...]
}
[...]
}
In the thread I have to read a file and update some TextFields in the layout. I've tried implementing the run() method with a while(true) that reads and updates the fields, but the app just crashes when I start that Activity.
UPDATE: I've called the execute() method inside the onCreate() method of the UI Activity. The Task is only working the first time I enter the Activity, if i change and go back it won't do anything.
Hey a solution could be trying to use Java's Executor Framework. Put the following code in your Activity.
With executors, you can use a cachedThreadPool() singleThreadExecutor() fixedThreadPoolExecutor(int numOfThreads) etc.
Executors.newSingleThreadExecutor().submit(new Runnable() {
#Override
public void run() {
//Your task here.
}
});
Please note there are numerous Threading Models and techniques in Android, some Android Specific, some based in Android.
AsyncTask
HandlerThread
You can use an AsyncTask. It allows you to load the file and show the progress on ui thread until the load it's finished.
Here you have a good example Download a file with Android, and showing the progress in a ProgressDialog
I would recommend using RxJava or Live Data if you are more advance in developing but also the first solution is fine enough for beginning
https://developer.android.com/topic/libraries/architecture/livedata.html
I have some fragments loaded in a ViewPager, where each "page" is loaded from a row in a cursor. Each fragment shows an image (JPEG) on the device. When the user dismisses the fragment (i.e swipe/page change, hits back/up, or just closes the app entirely) I want to invoke a method which opens the JPEG file for writing and does an update of its metadata. The actual work is eventually handled by the Apache Commons Imaging library.
I've implemented this by invoking my saveToFile() method from each fragment's life cycle onStop() handler. Does this mean the entire file operation ends up running on the UI thread? Should I definitely set up an AsyncTask for this?
Say the file write for some reason suddenly (for some jpeg) should take a long time, eg 2 minutes. What would then happen? Would the UI just wait (freeze) at this page/fragment before resuming? Or would the process (write to file) carry on "in the background" somehow? Or would the process just be killed, stopped short mid-process?
The way I have this wired up currently (onStop invoking saveToFile(), which calls up the imaging library and then updates the file) seems to work as it should. Even if I end the app, I still see my Toast text popping up, saying "Writing to file..." Seemingly, the process is never disturbed, and I can't say I'm experiencing any UI lag.
onStop() handler. Does this mean the entire file operation ends up
running on the UI thread? Should I definitely set up an AsyncTask for
this?
YES
An AsyncTask has several parts: a doInBackground method that does, in fact, run on a separate thread and the onPostExecute method that runs on the UI thread.
You can also use some sort of observer pattern such as EventBus to run async and post results to the UI.
Say the file write for some reason suddenly (for some jpeg) should
take a long time, eg 2 minutes. What would then happen? Would the UI
just wait (freeze)
The application will crash because Android will forcefully close it due to ANR (Application Not Responding).
Refer to the official documentation for details on this: https://developer.android.com/training/articles/perf-anr.html
Android applications normally run entirely on a single thread by
default the "UI thread" or "main thread"). This means anything your
application is doing in the UI thread that takes a long time to
complete can trigger the ANR dialog because your application is not
giving itself a chance to handle the input event or intent broadcasts.
Therefore, any method that runs in the UI thread should do as little
work as possible on that thread. In particular, activities should do
as little as possible to set up in key life-cycle methods such as
onCreate() and onResume(). Potentially long running operations such as
network or database operations, or computationally expensive
calculations such as resizing bitmaps should be done in a worker
thread (or in the case of databases operations, via an asynchronous
request).
The most effective way to create a worker thread for longer operations
is with the AsyncTask class.
Here is what I recommend though. Use the above mentioned, EventBus and create a BaseActivity which will automatically save the data for you onClose() by firing an event that runs Async. You then extend that base activity in all the places where you need autosave capabilities.
Here's what I mean with an example that uses EventBus.
public abstract class BaseActivity extends Activity{
#Override
protected void onResume(){
if(!EventBus.getDefault().isRegistered(this))
EventBus.getDefault().register(this);
super.onResume();
}
#Override
protected void onDestroy() {
if(EventBus.getDefault().isRegistered(this))
EventBus.getDefault().unregister(this);
super.onDestroy();
}
#Override
protected void onStop() {
super.onStop();
//We fire event and pass the current parent class that inherited this base.
EventBus.getDefault().post(new EventBusProcessMySaveData(this.getClass()));
}
}
//Your model class to use with EventBus
public final class EventBusProcessMySaveData{
private final Class className;
public EventBusProcessMySaveData(final Class className){
this.className = className;
}
public Class getClassName(){
return this.className;
}
}
public class MyMainActivity extends BaseActivity{
//Do you standard setup here onCreate() and such...
//Handle Event for Saving Operation, async.
//This will fire everytime theres an onClose() IN ANY activity that
//extends BaseActivity, but will only process if the class names match.
#Subscribe(threadMode = ThreadMode.ASYNC)
public void methodNameDoesNotReallyMatterHere(final EventBusProcessMySaveData model){
//We make sure this is the intended receiving end by comparing current class name
//with received class name.
if(model.getClassName().equals(this.getClass())){
//Do whatever you need to do that's CPUintensive here.
}
}
}
I have a Thread with open socket connection in a activity, I like to use the thread globaly so that I can get data from thread in other Activities. Somethink like running on the background...
Does anyone have a solution or examples for me?
Thank u.
You are looking for Service
or try this code
void runInBackground() {
new Thread(new Runnable() {
#Override
public void run() {
// DO your work here
// get the data
if (activity_is_not_in_background) {
runOnUiThread(new Runnable() {
#Override
public void run() {
//uddate UI
}
});
}
runInBackground();
}
});
}
And the third method using Async Task-- Understanding AsyncTask
If you want multiple activities to have access to this thread then I would combine Vaibs_cool's sample of running a thread (it's just a normal Thread, nothing Android specific about it) and then...
extend Application (make an entry for it in the Manifest) and put that Thread in there.
That way all your activities can talk to it.
You have two options:
Service
AsyncTask
If you want to open socket and make it opened even after Activity close use Service
On other hand if you want to open socket during Activity is running and close on Activity close then use AsyncTask
You can find example how to use AsyncTask here
From Docs:
Network operations can involve unpredictable delays. To prevent this from causing a poor user experience, always perform network operations on a separate thread from the UI. The AsyncTask class provides one of the simplest ways to fire off a new task from the UI thread.
I am confused with respect to design of my app. I need to continuously poll a server to get new data from it. I am confused whether Async Task running at fixed interval or Service running is background is better option. The thread will run only when the app is running
You have already some answers to your question, but I think it worths a summary ...
What you need
When you want to run a peice of code that takes some time to complete you should always run it in a separate thread from the UI thread.
You can achieve that in 2 ways:
Using Thread:
This is the simplest one, if you don't need a lot of communication from the new thread to the UI thread. If you need the communication, you will probably have to use a Handler to do it.
Using AsyncTask:
Also runs in a separate thread and already implements some communications channels with the UI thread. So this one is preferable if you need this communication back to the UI.
What you don't need
Service
This serves mainly to keep some code running even after you exit the main application, and it will run in the UI thread unless you spawn a new thread using the options described above. You said that your thread are suposed to terminate when you exit application, so this is not what you need.
IntentService
This can be activated by an external event (i.e. BroadcastReceiver) that can start a piece of code defined by you, even if your application is not running. Once again, based on your requirements, this is not what you are looking for.
Regards.
an Android Service is not in a background thread.
Therefore you should have a Service running that will start an ASyncTask each time you want to poll.
Note that services, like other application objects, run in the main thread of their hosting process. This means that, if your service is going to do any CPU intensive (such as MP3 playback) or blocking (such as networking) operations, it should spawn its own thread in which to do that work. More information on this can be found in Processes and Threads. The IntentService class is available as a standard implementation of Service that has its own thread where it schedules its work to be done.
Service should not be compared to AsyncTask. I guess you most likely meant IntentService here - and this is slightly different thing than Service, despite the common name.
As for periodical fetching, I'd stick with recurrent alarm (using AlarmManager) and (most likely) use IntentService to do the fetching.
Here you got with AsyncTask fundamentals and some tutorials
And here you got with IntentService fundamentals and tutorials
Note, that IntentService jobs are queued by design, while AsyncTasks can run fully paralel. However be aware of regression related to AsyncTask handling in newer APIs. Not a big deal as workaround is just a few more code lines, however it's worth knowing that.
EDIT
There's misunderstanding floating among many concerning AsyncTask lifecycle being bond to Activity's life cycle. This is WRONG. AsyncTask is independent from an Activity. Finishing Activity does not do anything to any AsyncTasks, unless you are cleaning them up from onDestroy() by your code. Yet, if an activity's process is being killed while it is in the background, then AsyncTask will also be killed as well, as part of the entire process being killed
If you want to "continuously poll", an asyncTask won't do. The task stops when your app gets stopped by Android. A Service by itself won't do either, as Blundell already pointed out. A Service runs in the main thread, and you don't want to do polling in the main thread. There's two ways of doing it: you create a Service that spawns its own thread to do the stuff you want it to do, or you let it schedule polls that are executed in an AsyncTask or in a separate thread. I try not to have polling in my app, but if you have to, creating a special thread in your service that does the polling seems best to me.
Depending on what your app does and what the polling is about, you can give the separate thread a lower priority, so it doesn't get in the way of other processing.
The thread will run only when the app is running
Then AsyncTask will be the simplest solution. Send data periodically to app thread using publishProgress() from background thread. Set desired interval using Thread.sleep() in doInBackground(). Also, make sure you start a new task in onResume() method of Activity, and end this task in onPause() method of Activity.
Example:
public class MyActivity extends Activity {
private AsyncTask<Void,String,Void> mAsyncTask;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
protected void onResume() {
super.onResume();
mAsyncTask = new MyTask();
mAsyncTask.execute();
}
#Override
protected void onPause() {
super.onPause();
if(mAsyncTask != null){
mAsyncTask.cancel(true);
}
}
private void onServerResponse(String response){
Toast.makeText(this, "Got response !", Toast.LENGTH_SHORT).show();
}
private final class MyTask extends AsyncTask<Void,String,Void>{
#Override
protected Void doInBackground(Void... voids) {
while (!isCancelled()){
String response = "";
//server query code here
publishProgress(response);
Log.i("TEST", "Response received");
//sleep for 5 sec, exit if interrupted ,likely due to cancel(true) called
try{
Thread.sleep(5000);
}catch (InterruptedException e){
return null;
}
}
return null;
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
if(values.length > 0){
onServerResponse(values[0]);
}
}
}
}
say for example I have this code in my activity:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Thread cThread = new Thread(new Runner());
cThread.start();
}
private NotifyMe(){
//do something here
}
and this is my Runner class:
public class TCPClient implements Runnable {
public void run(){
//call NotifyMe() [THIS IS MY QUESTION]
}
}
I have a thread on my activity that runs the Runner Class.
Once the thread start, I would like to call the NotifyMe() function
that is located at the activity. Is this possible?
Please let me know if you don't understand my question.
You can add a Constructor to the TCPClient that takes a reference to the activity, change the notifyMe method to public and then call the notifyMe method on the activity object that is stored in the thread.
The problem you would get with this is that activities may be closed, paused, destroyed while your thread is running. To check if the activity is still active use the isFinishing() method from the activity.
This solution is somewhat dangerous if your activity uses a lot of memory because the reference to the activity in the thread will let the garbage collector not reclaim the memory used by the drawables of the UI in the activity etc. until the thread is executed and can be garbage collected as well. If your activity is not that heavy in memory that should be ok. If it is or if you want to access the data from the thread from multiple activities have a look at this question.
A more or less unrelated note if you have a very small thread that won't run the whole time your app is running use a AsyncTask. This will allow you to simply put a single operation into the background.