向IntentService发送位置更新

11

如何直接将位置更新发送到 Intent Service?以下方法无效。 OnConnected 函数被调用,但是意图从未在服务中接收到:

...
    private PendingIntent getLocationPendingIntent(boolean shouldCreate) {
        Intent broadcast = new Intent(m_context,LocationUpdateService.class);
        int flags = shouldCreate ? 0 : PendingIntent.FLAG_NO_CREATE;
        return PendingIntent.getService(m_context, 0, broadcast, flags);
    }



    @Override
    public void onConnected(Bundle arg0) {
        PendingIntent locationPendingIntent = getLocationPendingIntent(true);        
        LocationRequest locationRequest = new LocationRequest();
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        locationRequest.setInterval(LOCATION_UPDATE_INTERVAL);
        locationRequest.setFastestInterval(LOCATION_FASTEST_UPDATE_INTERVAL);
        LocationServices.FusedLocationApi.requestLocationUpdates(m_googleApiClient, locationRequest,locationPendingIntent);
}
...

Intent Service:

import android.app.IntentService;
import android.content.Intent;
import android.util.Log;

public class LocationUpdateService extends IntentService {

    public LocationUpdateService() {
        super(LocationUpdateService.class.getName());
    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startID) {
        super.onStartCommand(intent, flags, startID);
        Log.d("LocationUpdateService","Location received");
        return START_REDELIVER_INTENT;
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Log.d("LocationUpdateService","Intent received");

    }   
}

清单文件:

...
<service  android:name=".LocationUpdateService" />
...

您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - kamokaze
4个回答

20

以下是经过实际测试的可行代码,它成功地将IntentService设置为接收包含用于位置更新的PendingIntent中所包含Intent的接收者。该代码基于此处的代码。

首先是IntentService

import android.app.IntentService;
import android.content.Intent;
import android.location.Location;
import android.util.Log;
import com.google.android.gms.location.FusedLocationProviderApi;
import com.google.android.gms.location.LocationResult;

public class LocationUpdateService extends IntentService {

    private final String TAG = "LocationUpdateService";
    Location location;

    public LocationUpdateService() {

        super("LocationUpdateService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        if (LocationResult.hasResult(intent)) {
            LocationResult locationResult = LocationResult.extractResult(intent);
            Location location = locationResult.getLastLocation();
            if (location != null) {
                 Log.d("locationtesting", "accuracy: " + location.getAccuracy() + " lat: " + location.getLatitude() + " lon: " + location.getLongitude());
            }
        }
    }
}

以下是注册使用 PendingIntent 并发送到 IntentService 的位置更新的 Activity 代码:

import android.app.PendingIntent;
import android.os.Bundle;
import android.content.Intent;
import android.app.Activity;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;

public class MainActivity extends Activity implements
        GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {

    LocationRequest mLocationRequest;
    GoogleApiClient mGoogleApiClient;
    PendingIntent mRequestLocationUpdatesPendingIntent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        buildGoogleApiClient();
        mGoogleApiClient.connect();
    }

    @Override
    protected void onPause(){
        super.onPause();
        if (mGoogleApiClient != null) {
            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, mRequestLocationUpdatesPendingIntent);
        }
    }

    protected synchronized void buildGoogleApiClient() {
        Toast.makeText(this,"buildGoogleApiClient",Toast.LENGTH_SHORT).show();
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
    }

    @Override
    public void onConnected(Bundle bundle) {
        Toast.makeText(this,"onConnected",Toast.LENGTH_SHORT).show();

        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(10);
        mLocationRequest.setFastestInterval(10);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
        //mLocationRequest.setSmallestDisplacement(0.1F);

        // create the Intent to use WebViewActivity to handle results
        Intent mRequestLocationUpdatesIntent = new Intent(this, LocationUpdateService.class);

        // create a PendingIntent
        mRequestLocationUpdatesPendingIntent = PendingIntent.getService(getApplicationContext(), 0,
                mRequestLocationUpdatesIntent,
                PendingIntent.FLAG_UPDATE_CURRENT);

        // request location updates
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,
                mLocationRequest,
                mRequestLocationUpdatesPendingIntent);
    }

    @Override
    public void onConnectionSuspended(int i) {
        Toast.makeText(this,"onConnectionSuspended",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        Toast.makeText(this,"onConnectionFailed",Toast.LENGTH_SHORT).show();
    }
}

生成的日志:

 D/locationtesting﹕ accuracy: 10.0 lat: 37.779702 lon: -122.3931595
 D/locationtesting﹕ accuracy: 10.0 lat: 37.7797023 lon: -122.3931594
 D/locationtesting﹕ accuracy: 10.0 lat: 37.7797022 lon: -122.3931596
 D/locationtesting﹕ accuracy: 10.0 lat: 37.7797021 lon: -122.3931597
 D/locationtesting﹕ accuracy: 10.0 lat: 37.7797021 lon: -122.3931596
 D/locationtesting﹕ accuracy: 10.0 lat: 37.7797019 lon: -122.3931597
 D/locationtesting﹕ accuracy: 10.0 lat: 37.7797019 lon: -122.3931597

我不知道为什么这对我不起作用。requestLocationUpdates被调用,但onHandleIntent没有被调用。 - Felipe Andrade

0

直接这么做是行不通的 - 我是说 requestLocationUpdates 并在 IntentService 中获取这些更新是不可能的。

您可以在后台中运行一个 Service,通过 requestLocationUpdates 请求这些更新,并在您需要时一直运行(要记住设备进入睡眠状态的情况)。然后从该 Service 中获得位置更新时,将其发送到IntentService 并在那里进行处理。


0

根据其性质,Intent服务适用于终端任务,例如从调用活动或片段接收意图,启动一些任务在单独的线程上,并静默完成,而不通知任何实体它的终止。文档中还有一个注意事项,即不应覆盖Intent服务的onStartCommand方法([IntentService][1])。我猜测您的服务在您期望它保持活动状态时结束了自己,因此意图未能正确传递。

绑定服务将是更合适的选择,因为它们允许不同的组件附加到自身并执行所需的通信。


我的想法是在Intent服务中处理位置更新,然后终止它直到下一次更新 - 对我来说,这看起来像完全可以接受的Intent服务使用方式,如果我错了,请纠正我。同时,我不确定你所说的“finishes itself”是什么意思,在这种情况下,我不应该从我的服务方法中看到任何日志记录吗? - M T
我明白了,那么是的,Intent Service 是这种目的的好选择。在这种情况下,您只需要覆盖 onHandleIntent 并在其中处理所有位置更新逻辑。尝试消除 onStartCommand,在 onHandleIntent 中放置您的日志语句,并查看是否根本调用了 onHandleIntent。 - dkarmazi
还是一样,我真的对这个问题感到困惑。你有什么建议从哪里开始调试吗? - M T
请您能否发布以下部分的更新代码:启动服务的活动或片段、服务本身以及声明服务的清单。调试服务的好起点是打开Android设备监视器,观察您的进程线程(按应用程序ID),并查看您的服务是否实际运行。 - dkarmazi

-1

你可以使用pendingIntent的getService()方法,在服务的onStartCommand()中获取对应的Intent。getBroadcast()发送一个广播,需要注册一个广播接收器来监听。希望这能帮到你。


我根据你的帖子更新了我的代码,但是我仍然无法在我的Intent Service中获取位置更新。请查看我在编辑后的问题中更新的代码。 - M T
检查是否正在调用onConnected()函数。 - Aks
这只是一个空操作,之后什么也没有发生。有什么想法可以调试吗? - M T

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接