简体   繁体   English

Android应用上未收到位置信息

[英]Location Not Received on Android App

I have an app that needs the location of the user, and I am new in implementing location service of Google. 我有一个需要用户所在位置的应用,而且我是Google实施位置服务的新手。 I made a separate java class to handle things related to getting location, and then using the location information in a activity just to show the location(so far), but I get the default value of 0 for latitude and longitude in my activity. 我创建了一个单独的java类来处理与获取位置相关的事情,然后使用活动中的位置信息来显示位置(到目前为止),但我的活动中的纬度和经度的默认值为0。

Here's the java class implementing the location related stuff, following google guideline: 以下是遵循google指南实现位置相关内容的java类:

import android.content.Context;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationServices;



public class CommentLocation implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {



private double mLatitude;
private double mLongitude;
private GoogleApiClient mGoogleApiClient;
private Location mLastLocation;



public CommentLocation(Context context){
    buildGoogleApiClient(context);
}



public double getCommentLongitude() {
    return mLongitude;
}

public double getCommentLatitude() {
    return mLatitude;
}



protected synchronized void buildGoogleApiClient(Context context) {
    mGoogleApiClient = new GoogleApiClient.Builder(context)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();
}



@Override
public void onConnected(Bundle connectionHint) {
    mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
    if (mLastLocation != null) {
        mLatitude = mLastLocation.getLatitude();
        mLongitude = mLastLocation.getLongitude();
    }
    else{
        Log.v(CommentLocation.class.getName(), "LOCATION WAS NOT RECEIVED");
    }
    Log.v(CommentLocation.class.getName(), "CONNECTION TO GET LOCATION IS SUCCESSFUL");
}

@Override
public void onConnectionSuspended(int i) {
    //TODO
    Log.v(CommentLocation.class.getName(), "CONNECTION TO GET LOCATION IS SUSPENDED");
}

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
    //TODO
    Log.v(CommentLocation.class.getName(), "CONNECTION TO GET LOCATION IS FAILED");
}

} }

And here is the caller of this location class (the fragment PostCommentFragment) 这是这个位置类的调用者(片段PostCommentFragment)

public class PostCommentFragment extends Fragment {



private TextView mLatitudeText;
private TextView mLongtitudeText;
private CommentDatabase database;
private CommentLocation location;



@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    database = new CommentDatabase(getActivity());
    location = new CommentLocation(getActivity());
    setHasOptionsMenu(true);    
}




@TargetApi(11)  //for setDisplayHomeAsUpEnabled function
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.fragment_post_comment, container, false);

    //to enable the app icon to work as a button and get the caret to appear in fragment's view
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){
        if(NavUtils.getParentActivityName(getActivity()) != null) {
            getActivity().getActionBar().setDisplayHomeAsUpEnabled(true);
        }
    }


    mLatitudeText = (TextView) v.findViewById(R.id.latitude_text);
    mLongtitudeText = (TextView) v.findViewById(R.id.longitude_text);

    mLatitudeText.setText(String.valueOf(location.getCommentLatitude()));
    mLongtitudeText.setText(String.valueOf(location.getCommentLongitude()));


    return v;
}

What am I doing wrong here? 我在这做错了什么? I also added this line compile 'com.google.android.gms:play-services:7.8.0' to build.gradle(Module:app)->under dependencies, and asked for permission in Manifest. 我还将此行编译为'com.google.android.gms:play-services:7.8.0'到build.gradle(Module:app) - >依赖项下,并在Manifest中请求权限。 Thanks! 谢谢!

Issue 1: 问题1:

You're not calling connect() on mGoogleApiClient. 你没有在mGoogleApiClient上调用connect()

You need to call connect in order for onConnected() to be invoked: 您需要调用connect以便调用onConnected()

public CommentLocation(Context context){
    buildGoogleApiClient(context);
    mGoogleApiClient.connect(); //added
}

Issue 2: 问题2:

It looks like you're only using getLastLocation() . 看起来你只使用getLastLocation() This may work for your needs, but if you need a location, this method is not guaranteed to give one. 这可能适合您的需求,但如果您需要某个位置,则无法保证此方法。 The getLastLocation() method can and will return null. getLastLocation()方法可以并且将返回null。 The main problem is that it doesn't prompt a request to the OS for a new location lock, instead it just checks if there was a last known location from some other app's location request. 主要问题是它不会向操作系统提示请求新的位置锁定,而只是检查是否有来自其他应用程序位置请求的最后一个已知位置。 If no other app had recently made a location request, then you get a null location returned to you. 如果最近没有其他应用程序发出了位置请求,那么您将获得一个返回给您的空位置。

The only way to guarantee that you actually get a location is to request one, and this is done with a call to requestLocationUpdates(). 保证实际获得位置的唯一方法是请求一个,这是通过调用requestLocationUpdates()来完成的。

Issue 3: 问题3:

Given that it takes time to connect to the Google Api Client, the timing may be off, and even if you get a location from getLastLocation() , you may have already requested it from your Fragment. 鉴于连接到Google Api客户端需要时间,时间可能会关闭,即使您从getLastLocation()获取位置,您可能已经从Fragment请求了它。

To get around this issue, you could use a BroadcastReceiver to send the location from the CommentLocation class to the Fragment. 要解决此问题,您可以使用BroadcastReceiver将位置从CommentLocation类发送到Fragment。

Note that in general keeping the location functionality encapsulated is a better approach, but it's more work to implement. 请注意,通常保持封装的位置功能是一种更好的方法,但实现起来还需要做更多的工作。 You might want to go with a more simple design, where the location functionality is within the Activity that is associated with this Fragment. 您可能希望采用更简单的设计,其中位置功能位于与此Fragment关联的Activity中。 Then you could just call into the Fragment when a location is available. 然后你可以在一个位置可用时调用Fragment。

Sample Activity code with a location listener: 带有位置侦听器的示例活动代码:

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

    LocationRequest mLocationRequest;
    GoogleApiClient mGoogleApiClient;

    @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, this);
        }
    }

    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.setPriority(LocationRequest.PRIORITY_LOW_POWER);
        //mLocationRequest.setSmallestDisplacement(0.1F);

        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
    }

    @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();
    }

    @Override
    public void onLocationChanged(Location location) {

        Log.d("locationtesting", "accuracy: " + location.getAccuracy() + " lat: " + location.getLatitude() + " lon: " + location.getLongitude());

        Toast.makeText(this,"Location Changed",Toast.LENGTH_SHORT).show();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM