1

我在从 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
    }
}
4

0 回答 0