I want to know mechanism of Download Managers (not the DownloadManager class introduced in API 9), as in my current project, I need to implement a few things same as download manager.
My basic understanding is that it uses a Service to download files. But what I cannot understand is how will it handle the multiple file download request, e.g. A file is currently being downloaded. Now user adds another file to be downloaded. I don't think a single Service can handle it. Can it? or is there some other method to do it? Any suggestions?
PS forgive me if the question is not clear enough because I myself don't understand my doubt very clearly. :(
They are using a MultiThreaded Socket Wheel.
Means, there is a ForegroundService which handle different Threads within the Service.
The ForegroundService make sure that it will be kept alive. The Threads itself are single Processes which run in a Background Thread.
Threre are several ThreadExecutors available which make sure that you have only a few Threads running paralell or process them thread by thread.
Here is a good tutorial making a SocketWheel http://www.javaspecialists.eu/archive/Issue023.html
Sources:
ThreadExecutor http://developer.android.com/reference/java/util/concurrent/ThreadPoolExecutor.html
ThreadPoolExecutor ExectuorService vs ThreadPoolExecutor (which is using LinkedBlockingQueue)
ForegroundService Android - implementing startForeground for a service?
Edited: for some code
public class DLService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Notification note=new Notification(R.drawable.somegraphics, "some title", randomnr);
Intent i=new Intent(this, ActivityClassToOpenWhenClicked.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pi=PendingIntent.getActivity(this, 0, i, 0);
note.setLatestEventInfo(this, "downloadmanager","downloading.. nothing", pi);
note.flags|=Notification.FLAG_NO_CLEAR;
startForeground(1337, note);
// if (intent.hasExtra("dlurl")) {
new Thread(new Runnable() {
public void run() {
new Client("http://yourfile.com/file.jpg");
}
}).start();
return START_NOT_STICKY;
}
class Client {
public Client(String filetodownload) throws Exception {
//do your http connection. for example one download #
// HttpUrlConnection httpConnection = new .....
}
}
}
Its just a quick coded example, not tested. But it shows the concept.
The service itself accept a Intent which can be a url where the file is located. Then it creates a new Thread which do the job. The Thread will run aslong as it takes to download the file. The foregroundService makes sure that the Service will be kept alive. You can also create a ThreadPoolExecutor which handle multiple Thread at onec. Read http://developer.android.com/training/multiple-threads/create-threadpool.html for instructions.
Related
I have been scouting around for a while, but cannot locate any information for calling final() using started services... or rather, when not using bound services. There is tons of info for bound services, but I already have two pretty large "started services" without binding, so I didn't want to modify the existing services more than absolutely necessary.
My app works by reading bluetooth data every 10 seconds, and depending on the data read, the Service will change to a new activity. However, I cannot call final() from my services, so I fear that I might be endlessly stacking activities while the application/services are running.
To change activities, I had to add Intent.FLAG_ACTIVITY_NEW_TASK. Considering the below image/definition from the developer's page, this flag looks like it might already handle my stacking issue? I do NOT allow for users to use the back button on their phones as everything is handled via confirm/cancel buttons and the services. My app MUST be this way for a few reasons. Thus, keeping the stack order isn't important to my application.
Key Points -
I want to ensure i'm not stacking up activities endlessly when starting new activities
Flagging "new task" when starting activities via my services
Stack order is not important to my app
Below is a very small cut of my code with comments to explain what i'm trying to do. Please make sure to look to the onDestroy() method of this service.
public class AlertService extends Service {
final class Threader implements Runnable{
// Scans bluetooth advertisement packets every 10 seconds
// Thread Runs until interrupted
// Stops service via service ID
stopSelf(this.serviceID);
}
#Override
public void onCreate(){
super.onCreate();
}
// Runs a thread until alert is found.
// Alert calls thread.interrupt()
#Override
public int onStartCommand(Intent intent, int flags, int startID){
enableBluetooth();
// Start Thread
thread = new Thread(new Threader(startID));
thread.start();
return START_STICKY;
}
#Override
public void onDestroy(){
thread.interrupt();
Intent alertActivity = new Intent(this, AlertActivity.class)
alertActivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(alertActivity);
}
// Unused Method - We will not be binding
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
EDIT via recommendation to use android:taskAffinity -
Using android:taskAffinity won't help me in this situation. By default, all activities in an application have the same affinity. When I create a new task by setting Intent.FLAG_ACTIVITY_NEW_TASK in the intent flags, the new activity will STILL be started in the same task if the activity has the same taskAffinity of the root activity in the task. Since I am just using the default affinity, everything should have the normal stack flow. I just cannot call finish(), which means that I am stacking up tons of activities.
To answer my own question, each new activity called via Intent.FLAG_ACTIVITY_NEW_TASK, was creating a new instance of each activity and putting it on the stack. This is true. However, each activity is NOT making a new Task, which was one of my fears as well.
When I create a new task by setting Intent.FLAG_ACTIVITY_NEW_TASK in the intent flags, the new activity will STILL be started in the same task (not in a new task) if the new activity has the same taskAffinity of the root activity in the task. Since I am just using the default affinity, every activity I create is being put into the same task. This means that nothing is acting any differently than the normal flow of creating activities and such.
Though, since I have disable the back button for my application, these activities created by flagging a new task are not finished, destroyed, or removed from the stack. To solve this, I will use FLAG_ACTIVITY_CLEAR_TOP, which finds a running instance of an activity in the stack (if there is one) and closes all of the activities above it.
Since my application always starts with the home screen, then ends with the home screen, flagging "clear top" will always close all activities above my home screen. So, upon return to the home screen, the only item on the stack will be the home screen.
I will have to test this, but it seems that I will not call finish() from my home activity to achieve this result - Otherwise, upon returning to the home activity, not all of the stack will be cleared.
I am developing an app which displays data from a server. The server is not mine and it is not very stable. Making too many connections crashes the server.
I have one socket to the server in my main activity, but at times I want to open sub activities which read the data and display it. My problem is that I am unable to achieve this with the same socket and have to open a new socket for every activity.
Every activity has a thread which does the reading from the socket and updates the UI elements on that activity as needed.
To use the same socket in multiple activities, I tried to close the inputReader of an activity before starting the new activity, but that simply make the application hang. If I leave it open, then the new thread in the new activity never receives any data. Killing the thread before starting the new activity is not possible because the thread is generally blocked by the read() function.
Is there anyway that I can have a centralized thread which does the reading and then sends the data to all the other threads in other activities so that I don't have to open new sockets in every activity?
I feel that this is a very basic thing that I am asking, but yet I am unable to find a solution.
A pretty straightforward and simple approach is the following:
You create a new Service which runs in the background and communicates with the server through your socket
The Service receives data from the socket and forwards/broadcasts it to all of your Activities which are interested in receiving it (for example to update the UI) by using the LocalBroadcastManager
All of your Activities implement a BroadcastReceiver and receive the data from your Service inside the onReceive() method
To accomplish that, you should read the introduction to Services and BroadcastReceivers to get an idea of how they work. Also to get a basic overview first, you should read about the available App Components.
EDIT, to answer the question in the comment:
You can always stop the Service by calling stopService() but you can also do it differently if you don't want/need all the functionality of a Service. Instead of a Service you could also create a simple Thread or a HandlerThread which communinicates with the server. From inside of your Thread, you can then forward/broadcast the data to your Activities by using the technique mentioned above (LocalBroadcastManager).
Just to give you an example of the basic structure (code untested though):
class SocketThread implements Runnable
{
static final String SOCKET_DATA_RECEIVED = "com.your.package.SOCKET_DATA_RECEIVED";
static final String SOCKET_DATA_IDENTIFIER = "com.your.package.SOCKET_DATA";
private Context context;
SocketThread(Context c) {
context = c.getApplicationContext();
}
#Override
public void run() { // code running in your thread
// fetch data from socket ...
Intent intent = new Intent();
intent.putExtra(SOCKET_DATA_IDENTIFIER, data); // store data in your intent
// send data to registered receivers
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
// your code ...
}
}
Then you have your Activities, for example MyActivity1, MyActivity2, ... MyActivityN. They all register their embedded SocketDataReceiver to receive the broadcast intent SOCKET_DATA_RECEIVED, which is sent by your thread.
Inside your onReceive() methods you can then extract the data from your intent object by using the identifier SOCKET_DATA_IDENTIFIER.
public class MyActivity1 extends Activity
{
private SocketDataReceiver socketDataReceiver;
#Override
protected void onResume() {
super.onResume();
socketDataReceiver = new SocketDataReceiver();
LocalBroadcastManager.getInstance(this).registerReceiver(
socketDataReceiver, new IntentFilter(SocketThread.SOCKET_DATA_RECEIVED));
}
#Override
protected void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(this).unregisterReceiver(socketDataReceiver);
}
private class SocketDataReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent) {
// intent contains your socket data,
// get data from intent using SocketThread.SOCKET_DATA_IDENTIFIER
}
}
}
Basically you answered your question yourself:
I can have a centralized thread which does the reading and then sends the data to all the other threads in other activities.
Meaning: of course, such a thing is possible. But you have to sit down, design and implement it. You would start by defining a reasonable interface that allows your other threads to communicate with that central service, something like:
enum RequestType { DO_THIS, DO_THAT };
interface ServerConnectionService<T> {
List<T> performRequest(RequestType request);
}
Meaning: instead of having your different threads do "low level" talking on that socket, you create an abstraction that allows you to say: "when I need this kind of information, then I use my service; and it returns some specific answer to me). Of course, this is a very generic answer, but well, your question isn't exactly specific either.
The next step would then be to have some central (maybe singleton) implementation of that interface; which runs on its own thread, and can be used by other threads in a synchronized, well-defined way.
Final word of warning: if you don't own that server, and it has low quality and is causing trouble for you - that is not a good setup. Because no matter what you do in your code, if the server doesn't do a good job, users will perceive your app to be the problem. Users don't care if an operation fails because some remote server crashes. So the other aspect in your question is: right now, you are in a bad spot. You should spent some serious time to find ways out of there. Otherwise you will be wasting a lot of time to build workarounds for that server you are dealing with.
On my Android App, I'm implementing SignalR connection (https://github.com/erizet/SignalA) to connect to a Hub server to send requests and receive responses.
a sample of my code is as follows:
signalAConnection = new com.zsoft.SignalA.Connection(Constants.getHubUrl(), this, new LongPollingTransport())
{
#Override
public void OnError(Exception exception)
{
}
#Override
public void OnMessage(String message)
{
}
#Override
public void OnStateChanged(StateBase oldState, StateBase newState)
{
}
};
if (signalAConnection != null)
signalAConnection.Start();
There's also the sending bit
signalAConnection.Send(hubMessageJson, new SendCallback()
{
public void OnError(Exception ex)
{
}
public void OnSent(CharSequence message)
{
}
});
The sending and receiving will occur across activites, and some responses will be sent at random times regardless of the activity, also, the connection should be opened as long as the app is running (even if the app is running in the background) that's why I wish to implement the signalA connection as a background service
The question is should I implement it as:
1 - a Service (http://developer.android.com/reference/android/app/Service.html)
OR
2 - an Intent Service (http://developer.android.com/training/run-background-service/create-service.html)
Keeping in mind that I will need to send strings to the service and get response strings from the service.
I would be most grateful if someone would show me how to implement this kind of connection in code as a background service/intentservice.
Thanks for reading.
UPDATE:
Please see this demo activity made by the developer as how he implemented SignalA
https://github.com/erizet/SignalA/blob/master/Demo/src/com/zsoft/SignalADemo/DemoActivity.java
The problem is AQuery (which I know nothing about) is being used in this demo activity. Does AQuery run in the background all the time ?
The problem is, the latest update on SignalA mentions the following
I have changed the transport. LongPolling now uses basic-http-client
instead of Aquery for http communication. I've removed all
dependencies on Aquery.
Hence I'm not sure whether I should follow this demo activity or not
Update 2:
This is the thing that is confusing me most
in the IntentService, the OnHandleIntent method calls stopSelf after it finishes its tasks, when I actually want the code in the IntentService to keep running all the time
protected abstract void onHandleIntent (Intent intent)
Added in API level 3
This method is invoked on the worker thread with a request to process. Only one Intent is processed at a time, but the processing happens on a worker thread that runs independently from other application logic. So, if this code takes a long time, it will hold up other requests to the same IntentService, but it will not hold up anything else. When all requests have been handled, the IntentService stops itself, so you should not call stopSelf().
SignalA is running on the thread that creates and starts the connection, but all network access is done in the background. The remaining work on the starting thread is really lightweight, hence its perfectly ok to do it on the UI tread.
To answer your question, you need to have a thread running the signala connection. Therefore I think a Service is the best choice since SignalA need to be running all the time.
Regarding Aquery and the demo project. I removed all dependencies to Aquery in the libraries, not in the Demo. To be clear, you don't need Aquery to run SignalA.
In my case, what I wanted was a Service not an Intent Service, since I wanted something that would keep running until the app closes
I'd need to do that for the application I'm building right now, as strange at it would sound, if it could be stopped after some time has passed (let's say a pair of minutes) it would be even better, but if it cannot be done I don't think it's that big of a deal as I guess memory freeing service of Android can take care of this.
Anyway I've tried the following code
final URI uri= URI:parse("http://www.google.com");
new Thread(new Runnable() {
public void run() {
Intent intent=new Intent(Intent.ACTION_VIEW,uri);
context.setActivity(intent);
}
}).start();
And the browser starts but not in the background, it's completely shown, I've tried to exchange ACTION_VIEW for ACTION_USER_BACKGROUND, but with that the application fails.
Any idea? Thanks for your help.
i'm currently working on an app for the android os that requires to fetch data from a remote server from time to time.
as this "update" should be carried out even when the actual frontend app is not running, i implemented a remote service that is started on system boot. now i need to schedule a timer to start the update.
is the "Timer"-class the right one for this job? and if "yes": what is the difference between a "normal" Timer() and one started as a "daemon" by Timer(true)?
http://developer.android.com/reference/java/util/Timer.html isn't very helpful with this :(
EDIT:
ok - i see there are much more methods to do this than i expected. to clarify:
i want to execute some code at a time that is specified.
this timer is used to trigger the execution of code 7 days in the future. (i.e., every week at a given weekday and time)
the code should run WITHOUT waking the phone up if it is "sleeping" (screen dimmed).
when running the code, no activity should be started. i.e. no app pops up on the screen.
the code that is executed should fetch some data from the internet. if at this time no internet connection is available, the timer should be set to sth like 30 minutes and then try again.
after completing the code execution, the timer will be set for the next interval which will be 7 days later.
the timer should be started at system boot, e.g., if i reboot the phone, the timer should determine the next date to execute the code and schedule the timer. this has to work without ANY user interaction!
when "sleeping", the thread/service/timer/whatsoever should not consume any system resources if possible...
what i need is pretty much a simple unix cronjob.
i think anyone here knows "newsrob" for android? what i want to realize is pretty much the same as the newsrob-updateservice.
Use AlarmManager. This allows you to set your schedule, then exit your components. Your code does not need to remain in memory and will be triggered when the alarm sounds.
i implemented a remote service that is started on system boot
Please don't do that just for a scheduled task. Use AlarmManager.
If you want the work to be done while the phone is asleep, you will need to use a _WAKEUP alarm type and perhaps use something like my WakefulIntentService to keep the device awake while the work is being done.
I recently had to develop an application following the same pattern.
Here is how I designed it:
I created a service started either explicitely by the frontend when enabling it through a configuration dialog, either started by a BroadcastReceiver waiting for the activation of network connectivity:
<receiver android:name=".notifications.MyReceiver">
<intent-filter>
<action android:name="android.net.conn.BACKGROUND_DATA_SETTING_CHANGED"/>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
</intent-filter>
</receiver>
The service, when started, starts a new HandlerThread, and associates it with a Looper:
public class MyService extends Service {
private Looper serviceLooper;
private MyHandler serviceHandler;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
//Toast.makeText(this, "service started", Toast.LENGTH_SHORT).show();
HandlerThread thread = new HandlerThread("MyHandlerThread", Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
serviceLooper = thread.getLooper();
serviceHandler = new MyHandler(this, serviceLooper);
// initial message
serviceHandler.sendMessage(Message.obtain());
}
#Override
public void onDestroy() {
serviceLooper.quit();
//Toast.makeText(this, "service stopped", Toast.LENGTH_SHORT).show();
}
}
When the network goes down or if the frontend disables it, the service is stopped, as well as the looper.
Now, in the MyHandler, I actually get the updates from the server when receiving messages.
public class MyHandler extends Handler {
private final Context context;
public MyHandler(Context context, Looper looper) {
super(looper);
this.context = context;
}
#Override
public void handleMessage(Message msg) {
// handle message and perform update
// ...
// try again 30 minutes
this.sendMessageDelayed(Message.obtain(), 1000 * 60 * 30);
}
}
The trick as you can see, is to send itself a delayed message to be handled 30 minutes later.
The advantage of this solution over using the AlarmManager is that the phone will NOT be forcibly woken up at a designed time, meaning it plays nicer with the phone resources if not needed.
Moreover, I don't start the service at boot time, only when there's an active internet connexion, and I stop it as soon as the connexion is gone.
It's been pretty efficient so far.