我在从 AsyncTask 绑定到已建立的服务时遇到了一些问题。我在两个服务之间绑定没有问题。进一步的细节是我从命令链启动它(将初始化程序 Activity 作为上下文的一部分传递)。
如果我有目的仅从 SpecialActivity 启动,我可以在此链之外使用我的 SpecialService,但这不允许我拥有通过命令链实现可以实现的所需可配置性。
问题是,无论出于何种原因,FirstCommand 都不会绑定 SpecialService。有人可以在这里阐明问题吗?
流程是这样的:
MainActivity > SpecialActivity > CommandController > FirstCommand
public class MainActivity extends ViewBaseActivity {
private void startServices(){
Intent propertiesIntent = new Intent(this, PropertiesService.class);
startService(propertiesIntent);
Intent intentSpecialIntent = new Intent(this, SpecialService.class);
startService(intentSpecialIntent);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startServices();
}
}
public class RateActivity extends ViewBaseActivity {
public void onClickOfSomeButton(View v){
CommandController commander = new CommandController();
commander.executeMyCommand(this);
}
}
public class CommandController {
protected interface IRemoteAsyncTask {
public List<?> getResults();
public void setContext(ContextBase context);
};
protected class RemoteTask extends AsyncTask<String, Void, Object> implements IRemoteAsyncTask{
private ContextBase context = new ContextBase();
public RemoteTask() {
super();
// TODO Auto-generated constructor stub
}
public RemoteTask(ContextBase context) {
super();
this.context = context;
}
@Override
public List<?> getResults() {
// TODO Auto-generated method stub
return null;
}
@Override
protected Object doInBackground(String... params) {
// TODO Auto-generated method stub
String command = (String) params[0];
logger.debug("Command controller is attempting to launch ["+command+"]");
try {
getCatalog().getCommand(command).execute(getContext());
} catch (Exception e) {
logger.error(e.getMessage());
}
return null;
}
@Override
public void setContext(ContextBase context) {
this.context = context;
}
protected ContextBase getContext() {
return context;
}
}
public void executeMyCommand(ViewBaseActivity activity){
ContextBase context = new ContextBase();
context.put(ViewBaseActivity.class, activity);
RemoteTask backgroundTask = new RemoteTask(context);
backgroundTask.execute(COMMANDS.MY_COMMAND_CHAIN.toString());
}
}
public class FirstCommand implements Command{
private SpecialService specialService;
private ViewBaseActivity hostActivity;
private ServiceConnection specialServiceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
// This is called when the connection with the service has been
// established, giving us the service object we can use to
// interact with the service. Because we have bound to a explicit
// service that we know is running in our own process, we can
// cast its IBinder to a concrete class and directly access it.
specialService = ((GetService.LocalBinder)service).specialService();
logger.debug("Get service connection established: "+specialService.toString());
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
// Because it is running in our same process, we should never
// see this happen.
specialService = null;
}
};
@Override
public boolean execute(Context context) throws Exception {
// TODO Auto-generated method stub
logger.debug("Executing Special Command");
ViewBaseActivity activity = hostActivity = (ViewBaseActivity) context.get(ViewBaseActivity.class);
Intent intent = new Intent(activity.getApplicationContext(), SpecialService.class);
activity.bindService(intent, specialServiceConnection, activity.BIND_AUTO_CREATE);
logger.debug("Binding specialService");
while(null==specialService){
Thread.sleep(500);
}
logger.debug("Service invoking explicitly");
specialService.execute();
logger.debug("Finished with Special Command");
return false;
}
@Override
protected void finalize() throws Throwable {
super.finalize();
if(null!=specialService){
hostActivity.unbindService(specialServiceConnection);
}
}
}
public class SpecialService extends IntentService {
public SpecialService() {
super("SpecialService");
}
public class LocalBinder extends Binder {
public SpecialService specialService() {
// Return this instance of LocalService so clients can call public methods
return SpecialService.this;
}
}
private final IBinder mBinder = new LocalBinder();
private PropertiesService propertiesService;
private ServiceConnection propertiesConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
// This is called when the connection with the service has been
// established, giving us the service object we can use to
// interact with the service. Because we have bound to a explicit
// service that we know is running in our own process, we can
// cast its IBinder to a concrete class and directly access it.
propertiesService = ((PropertiesService.LocalBinder)service).getService();
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
// Because it is running in our same process, we should never
// see this happen.
propertiesService = null;
}
};
@Override
public int onStartCommand(Intent intent, int flags, int startId){
super.onStartCommand(intent, flags, startId);
bindService(new Intent(SpecialService.this, PropertiesService.class), propertiesConnection, Context.BIND_AUTO_CREATE);
logger.debug("Special Service has be requested!");
return START_STICKY;
}
@Override
public void onCreate(){
super.onCreate();
}
@Override
public void onDestroy(){
super.onDestroy();
unbindService(propertiesConnection);
}
@Override
protected void onHandleIntent(Intent intent) {
logger.debug("Get Service onHandleIntent has be requested!");
}
public void execute() {
//Do soemthing novel
}
}