Android 无限循环中的服务

Android 无限循环中的服务,android,android-service,parse-platform,Android,Android Service,Parse Platform,我想调用一个服务,该服务重复查询Parse.com数据库并监视特定属性。以下是我目前得到的结果: public class Battle extends Service { @Override public int onStartCommand(Intent intent,int flags,int startId) { Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show(); ParseUser c

我想调用一个服务,该服务重复查询Parse.com数据库并监视特定属性。以下是我目前得到的结果:

public class Battle extends Service {
@Override
public int onStartCommand(Intent intent,int flags,int startId)
{ 
    Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
     ParseUser currentUser = ParseUser.getCurrentUser();
     username = currentUser.getString("username");
    findinBackground();

     return START_STICKY;
}




private void findinBackground(){
//public void run() {
    // TODO Auto-generated method stub
    while(true)
    {
    query = ParseUser.getQuery();
     query.whereEqualTo("isAttacking", username);
     query.findInBackground(new FindCallback<ParseUser>() {
          public void done(List<ParseUser> objects, ParseException e) {
              if ((e == null)&(objects.size() != 0))
            {
                // The query was successful.

                    ParseUser attacker = objects.get(0);
                    String attackerName = attacker.getUsername();
                    Log.i("ambustest",attackerName);
                    makeToast(attackerName);

            } 
              else
              {
                Log.i("fd","Something went wrong.");
            }  
          }
        });
    }
}

}
公共类战斗扩展服务{
@凌驾
公共int onStartCommand(Intent Intent、int标志、int startId)
{ 
Toast.makeText(此“服务已启动”,Toast.LENGTH_LONG).show();
ParseUser currentUser=ParseUser.getCurrentUser();
username=currentUser.getString(“用户名”);
findinBackground();
返回开始时间;
}
私有void findinBackground(){
//公开募捐{
//TODO自动生成的方法存根
while(true)
{
query=ParseUser.getQuery();
查询。whereEqualTo(“isAttacking”,用户名);
findInBackground(新的FindCallback(){
公共void done(列出对象,parsee异常){
如果((e==null)和(objects.size()!=0))
{
//查询成功。
ParseUser攻击者=objects.get(0);
字符串attackerName=attacker.getUsername();
Log.i(“ambustest”,附件名称);
makeToast(attackerName);
} 
其他的
{
Log.i(“fd”,“出了点问题。”);
}  
}
});
}
}
}
此代码编译良好,但在运行时停止响应。以下是我的日志:

服务与UI在同一线程上运行。如果要执行耗时的操作,需要在单独的线程中启动它们。

您需要在单独的线程上调用服务

@Override
public int onStartCommand(Intent intent,int flags,int startId)
{ 
    Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
    ParseUser currentUser = ParseUser.getCurrentUser();
    username = currentUser.getString("username");
    new Thread()
    {
        public void run() {
            findinBackground();
        }
    }.start();

 return START_STICKY;
}

需要注意的是,Intent服务是在单独的线程上自动调用的,而常规服务则不是。

最好的解决方案是远程服务,该服务带有一个处理程序,可以报告您的客户端(活动)的更改

您的服务将在一个单独的进程中运行

首先,您需要一个AIDL-作为与服务和客户机通信的接口

// IRemoteService.aidl
package de.contecon.android.util.abstractservice;
interface IRemoteService {
   void registerCallback(IRemoteServiceCallback mCallback);
   void unregisterCallback(IRemoteServiceCallback mCallback);
}
您的服务可以是这样的

//RemoteService.java
    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId);
        return START_STICKY_COMPATIBILITY;
    }

    @Override
    public void onCreate() {
        // While this service is running, it will continually increment a
        // number.  Send the first message that is used to perform the
        // increment.
        mHandler.sendEmptyMessage(REPORT_MSG);
    }

@Override
    public IBinder onBind(Intent intent) {
        // Select the interface to return.  If your service only implements
        // a single interface, you can just return it here without checking
        // the Intent.
        if (IRemoteService.class.getName().equals(intent.getAction())) {
            return mBinder;
        }
//Example for a second Binder
       // if (IRemoteServiceSecondary.class.getName().equals(intent.getAction())) {
       //     return mBinderSec;
       // }
        return null;
    }
private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
        @Override
        public void registerCallback(IRemoteServiceCallback mCallback) throws RemoteException {
            if (mCallback != null) mCallbacks.register(mCallback);
        }
        @Override
        public void unregisterCallback(IRemoteServiceCallback mCallback) throws RemoteException {
            if (mCallback != null) mCallbacks.unregister(mCallback);
        }
    };
/**
     * Our Handler used to execute operations on the main thread.  This is used
     * to schedule increments of our value.
     */
    private final Handler mHandler = new Handler() {
        @Override public void handleMessage(Message msg) {
            switch (msg.what) {
                // It is time to bump the value!
                case REPORT_MSG: {
                    // Up it goes.
                    int value = ++mValue;
                    // Broadcast to all clients the new value.
                    final int N = mCallbacks.beginBroadcast();
                    for (int i=0; i<N; i++) {
                        try {
                            mCallbacks.getBroadcastItem(i).valueChanged(value);
                        } catch (RemoteException e) {
                            // The RemoteCallbackList will take care of removing
                            // the dead object for us.
                        }
                    }
                    mCallbacks.finishBroadcast();
                    // Repeat every 1 second.
                    sendMessageDelayed(obtainMessage(REPORT_MSG), 1*1000);
                } break;
                default:
                    super.handleMessage(msg);
            }
        }
    };
AndroidManifest.xml

<service
            android:name=".service.RemoteService"
            android:process=":remote"
            android:enabled="true" >
            <intent-filter>
                <!-- These are the interfaces supported by the service, which
                     you can bind to. -->
                <action android:name="de.your.path.util.abstractservice.IRemoteService" />

                <!-- This is an action code you can use to select the service
                     without explicitly supplying the implementation class. -->
                <action android:name="your.action.uri.code.REMOTE_SERVICE" />
            </intent-filter>
        </service>

<service
            android:name=".service.RemoteService"
            android:process=":remote"
            android:enabled="true" >
            <intent-filter>
                <!-- These are the interfaces supported by the service, which
                     you can bind to. -->
                <action android:name="de.your.path.util.abstractservice.IRemoteService" />

                <!-- This is an action code you can use to select the service
                     without explicitly supplying the implementation class. -->
                <action android:name="your.action.uri.code.REMOTE_SERVICE" />
            </intent-filter>
        </service>