Android服务asyncrounous:如何在运行onStartCommand

时间:2016-08-12 19:27:33

标签: android service

当连接建立onConnectedToGooglePlayService()时,我会创建与 google play服务建立连接的类。当新的mySerivce启动时,首先要建立与播放服务的连接,如代码中所示。

问题是连接到播放服务需要一些时间,我无法确定在调用onStartCommand时是否建立了连接,我无法从Intent获取信息。

所以我的问题是:处理这种情况的最佳方法是什么?我想在建立连接时创建一个全局变量和处理意图,但我不确定这是否是正确的方法。

public class myService extends Service implements ConnectedToGooglePlayService {
    GoogleApiClient mGoogleApiClient;

    @Override
    public void onCreate() {
        super.onCreate();
        new ConnectToGooglePlayService(this, this).connect();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onConnectedToGooglePlayService(GoogleApiClient mGoogleApiClient) {
        this.mGoogleApiClient = mGoogleApiClient;
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

}

3 个答案:

答案 0 :(得分:1)

由于Service绑定是一个异步进程,暂停执行代码的最简单方法是阻止整个线程的执行,并在连接Service后恢复它。

但是,在UI线程上调用onStartCommand()并且阻止它不是一个好主意,因此您必须将工作卸载到后台线程。如果您不需要并行执行,那么IntentService就足够了。但最常见的方法是这样的:

public class MyService extends Service implements ConnectedToGooglePlayService {

    private final Object MONITOR = new Object();

    GoogleApiClient mGoogleApiClient;

    @Override
    public void onCreate() {
        super.onCreate();
        new ConnectToGooglePlayService(this, this).connect();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        new Thread(new Runnable() {
            @Override
            public void run() {

                // this block of code "pauses" the thread until mGoogleApiClient is not null
                synchronized (MONITOR) {
                    while (mGoogleApiClient == null) {
                        try {
                            MONITOR.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }

                // do some stuff that require google API client 

            }
        }).start();
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onConnectedToGooglePlayService(GoogleApiClient mGoogleApiClient) {
        synchronized (MONITOR) {
            this.mGoogleApiClient = mGoogleApiClient;
            MONITOR.notifyAll();
        }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

}

我注意到的一件事是,您没有考虑远程Service意外断开的可能性。我不知道您的可靠性要求是什么,但它可能会导致一些奇怪的错误。

我写了一篇关于绑定IPC服务的博客文章,可能对您有所帮助:How to establish a reliable (crash and kill tolerant) connection to bound IPC (e.g. AIDL) Service in Android

答案 1 :(得分:0)

您不需要在服务上@override onStartCommand也不需要使用GoogleApiClient作为全局变量,更好的方法是:

public class myService extends Service  {

   @Override
   public int onStartCommand(final Intent intent, final int flags, final int startId) {

         new ConnectToGooglePlayService(this, new ConnectToGooglePlayService(this, new ConnectedToGooglePlayService(){
         @Override
         public void onConnectedToGooglePlayService(GoogleApiClient mGoogleApiClient) {
            // you can access the on start command parameters because you
            // set the variables to be unchangeable by using the word final
         }
         }).connect();

         return super.onStartCommand(final intent, flags, startId);
   }


    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

}

答案 2 :(得分:-1)

看看它是否有效。

public class myService extends Service implements ConnectedToGooglePlayService {
GoogleApiClient mGoogleApiClient;

@Override
public void onCreate() {
        super.onCreate();
        new ConnectToGooglePlayService(this, this).connect();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
        while(mGoogleApiClient == null || !mGoogleApiClient.isConnected()) {
                Log.d("mGoogleApiClient status", "connecting...");
        }

        return super.onStartCommand(intent, flags, startId);
}

@Override
public void onConnectedToGooglePlayService(GoogleApiClient mGoogleApiClient) {
        this.mGoogleApiClient = mGoogleApiClient;
}

@Nullable
@Override
public IBinder onBind(Intent intent) {
        return null;
}

}