Good day! Stumbled upon the following problem with LocationServices , I can not get the current location. The findLocation() method findLocation() . The problem is that LocationServices.FusedLocationApi.requestLocationUpdates does not call onLocationChanged , and LocationServices.FusedLocationApi.getLastLocation(mClient); returns null .

And the problem is also solved by restarting the emulator ... And for some reason on my nexus 5 android 6.0.1 crashes with an error ... I would be grateful for any hint.

All code below.

 import java.util.ArrayList; import java.util.List; import java.util.Locale; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.location.LocationRequest; import com.google.android.gms.location.LocationServices; import com.google.android.gms.location.LocationListener; import android.app.ProgressDialog; import android.content.ContentValues; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.location.Address; import android.location.Criteria; import android.location.Geocoder; import android.location.Location; import android.location.LocationManager; import android.os.Bundle; import android.provider.Settings; import android.support.v4.app.Fragment; import android.support.v7.app.AlertDialog; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import static android.content.ContentValues.TAG; public class LocationFragment extends Fragment{ //Widget private Location mLocation; private TextView mCityResultTextView; private TextView mLongitudeTextView; private TextView mLatitudeTextView; //List Widget&Adapter private RecyclerView mLocationRecyclerView; private LocationAdapter mAdapter; //DataStorage private List<CityLocation> mCityLocations; private SQLiteDatabase mDatabase; //Location private LocationManager mLocationManager; private GoogleApiClient mClient; private ProgressDialog mDialog; public static LocationFragment newInstance() { return new LocationFragment(); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mClient = new GoogleApiClient.Builder(getActivity()) .addApi(LocationServices.API) .addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() { @Override public void onConnected(Bundle bundle) { findLocation(); } @Override public void onConnectionSuspended(int i) { } }) .build(); mDatabase = new LocationBaseHelper(getContext()) .getWritableDatabase(); mCityLocations = getCityLocations(); mLocationManager = (LocationManager)getActivity().getSystemService(Context.LOCATION_SERVICE); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.fragment_location, container, false); mCityResultTextView = (TextView) v.findViewById(R.id.city_result_textView); mLongitudeTextView = (TextView) v.findViewById(R.id.longitude_result_textView); mLatitudeTextView = (TextView) v.findViewById(R.id.latitude_result_textView); mLocationRecyclerView = (RecyclerView) v.findViewById(R.id.location_recycler_view); LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity()); layoutManager.setReverseLayout(true); layoutManager.setStackFromEnd(true); mLocationRecyclerView.setLayoutManager(layoutManager); Button addLocationButton = (Button) v.findViewById(R.id.add_location); addLocationButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //findCityLocation(); findLocation(); } }); updateUI(); return v; } private void updateUI(){ mCityLocations = getCityLocations(); if (mCityLocations.size() > 0) { CityLocation city = mCityLocations.get(mCityLocations.size() - 1); mLatitudeTextView.setText(city.getLatLocation()); mLongitudeTextView.setText(city.getLongLocation()); mCityResultTextView.setText(city.getCity()); if (mAdapter == null) { mAdapter = new LocationAdapter(mCityLocations); mLocationRecyclerView.setAdapter(mAdapter); } else { mAdapter.setCityLocation(mCityLocations); mAdapter.notifyDataSetChanged(); mLocationRecyclerView.smoothScrollToPosition(mAdapter.getItemCount() - 1); } } } private String getAddressFromLocation(){ Geocoder geocoder = new Geocoder(getContext(), Locale.getDefault()); try { List<Address> addresses = geocoder.getFromLocation(mLocation.getLatitude(), mLocation.getLongitude(), 1); if (addresses != null) { if (!addresses.get(0).getLocality().equals("")) { return addresses.get(0).getLocality(); } else { return "Нет адресов!"; } } else { return "Нет адресов!"; } } catch (Exception e) { e.printStackTrace(); return "Не могу получить адрес!"; } } private boolean checkLocation() { if(!isLocationEnabled()) showAlert(); return isLocationEnabled(); } private boolean isLocationEnabled() { boolean temp1 = mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); boolean temp2 = mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); return (temp1||temp2); } private void showAlert() { final AlertDialog.Builder dialog = new AlertDialog.Builder(getContext()); dialog.setTitle("Enable Location") .setMessage("Your Locations Settings is set to 'Off'.\nPlease Enable Location to " + "use this app") .setPositiveButton("Location Settings", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface paramDialogInterface, int paramInt) { Intent myIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); startActivity(myIntent); } }) .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface paramDialogInterface, int paramInt) { } }); dialog.show(); } public void findLocation(){ if(!checkLocation()) return; LocationRequest request = LocationRequest.create(); request.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); request.setNumUpdates(1); request.setInterval(0); LocationServices.FusedLocationApi .requestLocationUpdates(mClient, request, new LocationListener() { @Override public void onLocationChanged(Location location) { Log.i(TAG, "Got a fix: " + location); mLocation = location; CityLocation cityLocation = new CityLocation(); if (mLocation != null) { //получаем адрес cityLocation.setCity(getAddressFromLocation()); //подготавливаем данные для БД cityLocation.setLocation(mLocation); mCityLocations.add(cityLocation); addLocations(cityLocation); //Обновляем представление updateUI(); } else { Toast.makeText(getContext(), "Location not Detected", Toast.LENGTH_SHORT).show(); cityLocation.setCity( "Location not Detected"); } } }); //реализация вторая LocationServices.FusedLocationApi.getLastLocation(mClient); CityLocation cityLocation = new CityLocation(); if (mLocation != null) { Toast.makeText(getContext(), mLocation.toString(), Toast.LENGTH_SHORT).show(); //получаем адрес cityLocation.setCity(getAddressFromLocation()); //подготавливаем данные для БД cityLocation.setLocation(mLocation); mCityLocations.add(cityLocation); addLocations(cityLocation); //Обновляем представление updateUI(); } else { Toast.makeText(getContext(), "Location not Detected", Toast.LENGTH_SHORT).show(); cityLocation.setCity( "Location not Detected"); } } //Database private static ContentValues getContentValues(CityLocation cityLocation) { ContentValues values = new ContentValues(); values.put(LocationTable.Cols.TITLE, cityLocation.getCity()); values.put(LocationTable.Cols.LATITUDE, cityLocation.getLatLocation()); values.put(LocationTable.Cols.LONGITUDE, cityLocation.getLongLocation()); return values; } public void addLocations(CityLocation cityLocation) { ContentValues values = getContentValues(cityLocation); mDatabase.insert(LocationTable.NAME, null, values); } private CityLocationCursorWrapper queryCityLocations(String whereClause, String[] whereArgs) { Cursor cursor = mDatabase.query( LocationTable.NAME, null, // Columns - null выбирает все столбцы whereClause, whereArgs, null, // groupBy null, // having null // orderBy ); return new CityLocationCursorWrapper(cursor); } public List<CityLocation> getCityLocations() { List<CityLocation> cityLocations = new ArrayList<>(); try (CityLocationCursorWrapper cursor = queryCityLocations(null, null)) { cursor.moveToFirst(); while (!cursor.isAfterLast()) { cityLocations.add(cursor.getCityLocation()); cursor.moveToNext(); } } return cityLocations; } @Override public void onStart() { super.onStart(); mClient.connect(); } @Override public void onStop() { super.onStop(); mClient.disconnect(); } } 

gradle:

 apply plugin: 'com.android.application' android { compileSdkVersion 25 buildToolsVersion "24.0.1" defaultConfig { applicationId "com.fgurbanov.skynet.in_search_hire_test" minSdkVersion 21 targetSdkVersion 22 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" // Enabling multidex support. multiDexEnabled true } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:25.1.0' testCompile 'junit:junit:4.12' compile 'com.android.support:recyclerview-v7:25.1.0' compile 'com.android.support:design:25.1.0' compile 'com.google.android.gms:play-services-location:10.0.1' compile 'com.android.support:multidex:1.0.1' } 

Manifesto

 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.fgurbanov.skynet.in_search_hire_test"> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.INTERNET" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <meta-data android:name="android.support.multidex.MultiDexApplication" android:value="@integer/google_play_services_version" />- <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> </application> </manifest> 
  • Flies out on your device because you did not give permission. Android 6 has such a thing as Runtime Permission. habrahabr.ru/post/278945 - pavel163

2 answers 2

Hi, Your code is big and clumsy) I can not read it because right now it is occupied by a servlet. But here's a working location code:

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="testing.gps_service.MainActivity"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Start Service" android:id="@+id/button" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Stop Service" android:id="@+id/button2" android:layout_alignTop="@+id/button" android:layout_alignParentRight="true" android:layout_alignParentEnd="true" /> <ScrollView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/scrollView" android:layout_centerHorizontal="true" android:foregroundGravity="top|right" android:layout_above="@+id/button" android:layout_alignParentTop="true" android:clickable="true"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:text="Coordinates: " android:id="@+id/textView" /> </ScrollView> </RelativeLayout> 

This markup and in this code (brain)):

 public class MainActivity extends AppCompatActivity { private Button btn_start, btn_stop; private TextView textView; private BroadcastReceiver broadcastReceiver; @Override protected void onResume() { super.onResume(); if(broadcastReceiver == null){ broadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { textView.append("\n" +intent.getExtras().get("coordinates")); } }; } registerReceiver(broadcastReceiver,new IntentFilter("location_update")); } @Override protected void onDestroy() { super.onDestroy(); if(broadcastReceiver != null){ unregisterReceiver(broadcastReceiver); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn_start = (Button) findViewById(R.id.button); btn_stop = (Button) findViewById(R.id.button2); textView = (TextView) findViewById(R.id.textView); if(!runtime_permissions()) enable_buttons(); } private void enable_buttons() { btn_start.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent i =new Intent(getApplicationContext(),GPS_Service.class); startService(i); } }); btn_stop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent i = new Intent(getApplicationContext(),GPS_Service.class); stopService(i); } }); } private boolean runtime_permissions() { if(Build.VERSION.SDK_INT >= 23 && ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED){ requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION},100); return true; } return false; } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if(requestCode == 100){ if( grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED){ enable_buttons(); }else { runtime_permissions(); } } } } 

...

 public class GPS_Service extends Service { private LocationListener listener; private LocationManager locationManager; @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { listener = new LocationListener() { @Override public void onLocationChanged(Location location) { Intent i = new Intent("location_update"); i.putExtra("coordinates",location.getLongitude()+" "+location.getLatitude()); sendBroadcast(i); } @Override public void onStatusChanged(String s, int i, Bundle bundle) { } @Override public void onProviderEnabled(String s) { } @Override public void onProviderDisabled(String s) { Intent i = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(i); } }; locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE); //noinspection MissingPermission locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,3000,0,listener); } @Override public void onDestroy() { super.onDestroy(); if(locationManager != null){ //noinspection MissingPermission locationManager.removeUpdates(listener); } } } 

    In general, the error was in saving data in SQLite. There was a problem with the conversion from Location.toString and back because of the system language, because in the Russian version, a comma and not a period is put in double. And the emulator did not correctly work out the preservation in the database and thus did not give the results of obtaining the location. Here is a very strange bug. Concerning permissions, since There were target sdk 22 problems with them should not be. And about writing a service to get a location, it’s not logical for such a small task as getting a location at the touch of a button.