I'm trying to implement a call screening service in my app. It seems the CallScreeningService class has really a bad design however. The abstract method onScreenCall is called on UI thread and it's not possible to use something different, in addition the method respondToCall must be called in onScreenCall because it's not possible to go async looking at AOSP source code. The code calls recycle() on onScreenCall arguments when it returns. The question: how is it supposed to work? We can't bind another service, we can't use an AsyncTask, even a load from database would be a problem since the access is performed on UI thread. Am I missing anything?
You can use rxjava or coroutines to access your data in background thread
Related
I want to control a RaspberryPi via android app and plan to do this by defining an api on the raspberry and accessing it via the app.
On the Android Developer Guides I found the recommendation to implement a DownloadCallback interface.
My question is, why would I want to do that, if I can alternatively simply use an AsyncTask and make an HttpRequest?
Using an AsyncTask for network calls is considered a bad idea. First, AsyncTask does not handle orientation correctly so you need to have more code put in so that the asynctask properly terminates (making sure it doesn't make calls to the finishing activity, making sure it doesn't hold any strong references to the finishing activity). You also cannot halt AsyncTask so lets say in your main UI thread, you want to stop the AsyncTask from performing the network call but you already started it. Well you are out of luck and you need to wait until it terminates on its own. (As mentioned in the comment below, this is not true. You can halt interrupt the thread of the AsyncTask to "cancel") Also, you cannot make parallel network requests in an AsyncTask easily.
Also this is more of a preference but using AsyncTask is more boilerplate code than I would like. Retrofit is my most preferred way of network operations.
DownloadCallback isn't about replacing the AsyncTask. It is just a way to communicate between your fragment (the one who started the network call) and the activity (the one who wants to know what the progress of the network call is) about the progress of your network operations. You can see here https://developer.android.com/training/basics/network-ops/connecting that they are still using AsyncTask for network operations but they are using the DownloadCallback to notify the activity about the progress of your operation.
I am developing an android application that needs to communicate a lot with a remote server. For this task I wrote a class that handles all the network communication.
Do I need to make for every single method as an Asynctask? What about methods that I am dependent on for the rest of the code execution? (thus needs to be done synchronously - like waiting for an answer on registration?)
I am asking this because I already had a small app before to communicate with a remote server and I didn't use any Asynctasks, this one crashes on every method being called though.
Edit -
Meanwhile - before making a class of my own I found a great tutorial related to a google libraray that already handle that the libraray name is Volley the tutorial I looked on is this one
Yes, every network call has to asynchronous. You don't need to make every single method in you class async, but i would refactor the code in a way that only one peace of code actually does the calls and this peace has to be async. If you have following code that depends on the response from the server, then use a callback.
In pseudo code that would look something like this:
void makeNetworkCall(command, listener){
async(){
result = command.execute();
listener.onCommandSuccess(result);
}
}
Do I need to make for every single method as an Asynctask?
Yes. Android requires networking code to be executed asynchronously, so the user interface never gets blocked.
What about methods that I am dependent on for the rest of the code execution?
You can wait for an Asynchtask to finish execution. Refer to this question.
Suppose I have an object I've created. We'll call it MyObject.
I'd like to be able to save MyObject to a database's corresponding table. I don't want this to happen on the Activity's main thread. Easy enough. I created an AsyncTask to do this.
However, my application also has an IntentService used to sync data between the device's database and my cloud database. I'd like to save MyObjects that have synced down from the cloud to the device's database from here, too. However, I do not wish for this to happen asynchronously in the IntentService. I want it to happen on the IntentService's main thread.
The purpose, obviously, is to modularize this code so it doesn't need to be duplicated.
How can I modularize my save code so that it can be called both asynchronously and synchronously?
I suspect I will create a saveMe() method inside the MyObject and declare it a static. From the IntentService, I simply call saveMe(). From an Activity, I will launch an AsyncTask which passes in the MyObject and then calls saveMe(). Does that sound right?
Besides the static that sounds good to me, don't you wish to access instance variables?
I don't know how your application is designed in general, but I'd probably go for one of the following patterns:
a subclass of Runnable (or Callable if you need return values and/or exceptions) that handles saving in general, with a suitable factory or constructor. You can then run these tasks directly or on background threads.
instances of objects have a method to save themselves (this is what you described), and these methods are used by synchronous or asynchronous code.
instances of databases / storage classes have a method to save MyObject instances, assuming they have a common parent class where you can put that code, and these methods are used by synchronous or asynchronous code.
The exact pattern depends on the application you're working on imho.
When I'm in a situation where I sometimes want to do something synchronously and sometimes asynch:
I tend to implement an IntentService with a public static method to do what I want usually called blockingX where X is what it does. This way, if I want to do it synchronously, I call the method directly. If I want to do it on a background thread, I send the service an intent.
I'm building an Android library to collect data from the host app and send this data to an online server in the background. I realize that this would require some sort of multi-threading/use of a service/forking.
The application simply keeps adding data through library calls, and the library should handle the sending of this data in the background without disturbing the main UI.
How should I got about making this library? Should the entire library run on an Android Service? Should I just use another thread? This is my first foray into parallelism. I'm not sure what the best way to do this is.
A detailed response is appreciated.
Some of the answers aren't quite correct. Services (Android Service component) are NOT made to run in the background, they run in the default UI thread.
In all honesty, the question shouldn't be service or thread or anything. Your library does NOT need to kick start a service, it could simply be a class (singleton/static, whatever it is) that should extend AsyncTask (or anything else running in the background that I'll explain in a bit) and use the doInBackground method to send stuff to the server. Note AsyncTask is nothing but a Thread internally. So here's what I would do:
Let's call your library's main class that interfaces with your server ServerHelper. You can make this a singleton (or static but that's a separate discussion). Within this class create an innerclass say ServerHelperCommandTask and extend AsyncTask. You really should review AsyncTask in detail to understand how that works. Because you would be asked to override doInBackGround. Anything you put in this method will autmoatically get exectued in a separate thread off the UI. Then a callback is invoked called onPostExecute that you can override as you will get the result from doInBackground here. This OnPostExecute is called in the mainThread so you can check for say error results here, etc etc.
This would be the simplest method; however, there are many other methods and libraries that help you with networking and deal with all the background stuff internally. Google just release a library called Volley which you may be able to plugin and use as it would do all the parallel processing for you. But that may take a bit of learning curve. Hope you understand AsyncTasks as in your case if the data pushed isn't a lot, then AsyncTasks is the way to go. Also note that you can call multiple AsyncTasks but while that seems on the surface that it is kicking off multiple parallel threads, that isn't quite accurate since honeycomb as internally you can call 5 Asynctasks but all 5 of those tasks will be executed sequentially so you wouldn't have to worry much about serializing.
Service would be a more reliable solution for situation You described.
I mean running background threads from service, not from Activity. Service itself does not provide separate thread by default, by the way.
The point is that Services have higher priority than acitivities so they will be destroyed with less probabilty, so your long-running task won't be interrupted.
You could do both but here's pros and cons for each solution :
Services are made to run in the background, even when your app is not in the foreground. sers usually don't like having services running for nothing.
From your description it seems that you would only need to have this thread running when the app is in foreground right ?
If so, a normal thread could do the job.
However, a service might be easier to implement.
Hope it helps
You should definitely use a Service in this situation. Async tasks and manually creating a thread is not really suitable for computations that need to run in the background for network communication. Use the Async task for long running local computations (e.g. for an algorithm doing sorting).
Note that if you use a service, it will by nature NOT run as a background thread! You need to handle threading manually. In order to save yourself from this hassle (especially if it is your first time with multi-threading) use an IntentService!
The IntentService may be invoked using the startService method as with any other service, but the IntentService class is able to handle multiple invocations as in a producer/consumer pattern. This means that you can queue commands automatically to the service just using the startService method. In the IntentService class that you make, you can then handle different types of commands by looking at the given action inside of the intent that is sent along as a parameter in the startService method.
Here is an example of how the implementation of an IntentService:
public class SimpleIntentService extends IntentService {
public SimpleIntentService() {
super("SimpleIntentService");
}
#Override
protected void onHandleIntent(Intent intent) {
String commnad = intent.getAction();
//handle your command here and execute your desired code depending on this command
}
}
I'm writing a XMPP Client using SMACK.
So when I want to update my contactList - the ListAdapter.notifyDataSetChanged requires to be run in the UI thread, but obviously the SMACK Library uses Multithreading on the RosterListener (which in fact is a good thing). But here is the problem: to run s.th. in the UI thread, I need a valid context.
But how do I get it? Passing the Context of the Activity down to the register function of the RosterListener was the first that came to mind - but I have some functions in different classes there before I even get to the register function, and I don't really like it to pass the context over and over again until it finally reaches its destination, where it will be used.
I guess, I'm not the only one, who has encountered this problem, so how would you solve it?
Maybe a Singleton, just to save this one Context (in my opinion an even less favourable idea...)
Or is maybe my whole design flawed?
Is there a possibility to get the UI thread from anywhere?
Bottom line: I don't really have a clue how to handle it, at the moment I'm passing the context as argument through multiple functions, but is there a better way to do it.
Thanks for any help.
Put XMPP code into Service and then send broadcasts. Interested Activities can simply register for those broadcasts. That way you'll never again worry about UI thread and availability of Activity context.
I found a neater and more modular way of doing it. For this you need to have defined an Application Context. Once you have that, you can call RunOnUIThread from any class library without the mess of having a reference to the Activity.
From anywhere within your class library call:
Handler handler = new Handler(Application.Context.MainLooper);
handler.Post(() => doStuff());
Please bear in mind that this is written in C# as I use MonoDroid, but I believe it is very similar to Java.
For how to create an ApplicationContext look at this thread
I do not get what exactly you try to do but if you are in some thread and you want to shitch back to UIThread than
Looper is your solution
http://developer.android.com/reference/android/os/Looper.html
Reading you, I get a feeling like you are working with callbacks. Smack or whatever that is is calling you back from a worker thread, and you want to post to the main UI thread when that happens.
In my experience, callbacks can always be associated to a custom piece of data, which you pass when registering the callback, and receive when you are actually called back.
In your context there are two approaches which I consider to be poor design:
using any kind of global thingy, call it a singleton if you like
let your Model expect and return the (Android-and-UI-specific) Context
Instead, I would create a small interface which is implemented by the Activity, have the Model accept an instance of this interface, and yes pass it over the different layers until registration.
The methods exposed by this interface will be called asynchronously, which you could document appropriately, to indicate that runOnUiThread() or similar must be used.
This way, you're not exactly passing the Context (which is a platform and UI detail) all over the place and into the Model. Plus, you avoid global/static data, which leads to various problems, conflicts and other memory leaks.