My app does the following:
Activity1 starts Activity2.
Acitivity2 starts a Service. The Service uses a AsyncTask to download a file.In the AsyncTask I have a piece of code like this:
while ((status == 0)) {
byte buffer[];
if (size - downloaded > MAX_BUFFER_SIZE) {
buffer = new byte[MAX_BUFFER_SIZE];
} else {
buffer = new byte[size - downloaded];
}
int read = stream.read(buffer);
if (read == -1)
break;
file.write(buffer, 0, read);
downloaded += read;
}
Everything works like expected. With the status
variable I can start and stop my download depending on its value.
BUT, when I close Activity2 and start it again (the service keeps running), I cannot stop the download, which means the variable status
is not read correctly. I checked the variable, the value is OK but the Asynctask does not recognize it.
How can I get back control over my AsyncTask?
I made some more tests but this time with a thread, to make sure its not a failure in how I handle the AsyncTask. I did it this way:
Activity2 starts the Service (I did not change any code here).
The Service creates an Download
Object what downloads the file using a Thread.
The structure looks like this:
in the Service
private Download dl = new Download();
private final DMInterface.Stub mBinder = new DMInterface.Stub() {
public void downloadFile() throws DeadObjectException {
try {
dl.start(url) // This starts a thread and the download
} catch (IndexOutOfBoundsException e) {
Log.e(getString(R.string.app_name), e.getMessage());
}
}
public void stop() throws DeadObjectException {
dl.cancel(); //This stops the download
}
};
And again, everything works until I disconnect from the service. Why am I only able to control the thread when I don't disconnect from the service?
Here is the code where I start/bind the service to Activity2 (only they important parts):
public class Activity2 extends ListActivity {
private DMInterface dmInterface;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.bindService(new Intent(Activity2.this, DMService.class), mConnection, Context.BIND_AUTO_CREATE);
}
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
dmInterface = DMInterface.Stub.asInterface(service);
//do some stuff
}
public void onServiceDisconnected(ComponentName className) {
dmInterface = null;
}
};
}
There are two scenarios. In the first one I get an error in the second one not (but nothing else happens). When an error is raised depends on, where i initialize the Thread e.g. the Object that starts the Thread.
Scenario 1:
When I开发者_Python百科 do it like described above, I get no error but nothing happens.
Scenario 2:
In the Service:
private Download dl;
private final DMInterface.Stub mBinder = new DMInterface.Stub() {
public void downloadFile() throws DeadObjectException {
try {
dl = new Download();
dl.start(url) // This starts a thread and the download
} catch (IndexOutOfBoundsException e) {
Log.e(getString(R.string.app_name), e.getMessage());
}
}
public void stop() throws DeadObjectException {
dl.cancel(); //This stops the download
}
};
When I try to reach other parts of the service (setting a variable or something like that) everything works OK.
A Service lives in its own world, being a Service it is remote from the rest of your program. A Binder can be used to communicate with your service. Defining a aidl interface with a setStatus method allows you to communicate the status to the service.
精彩评论