我正在使用android开发一个应用,其中用户可以通过反向地址解析获取地址。我做到了,直到三天前它都可以正常工作,但是现在它没有返回任何地址。
MainAtivity
public class Main2Activity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private static final int REQUEST_PERMISSIONS_REQUEST_CODE = 34;
private static final String ADDRESS_REQUESTED_KEY = "address-request-pending";
private static final String LOCATION_ADDRESS_KEY = "location-address";
/**
* Provides access to the Fused Location Provider API.
*/
private FusedLocationProviderClient mFusedLocationClient;
/**
* Represents a geographical location.
*/
private Location mLastLocation;
/**
* Tracks whether the user has requested an address. Becomes true when the user requests an
* address and false when the address (or an error message) is delivered.
*/
private boolean mAddressRequested;
/**
* The formatted location address.
*/
private String mAddressOutput;
/**
* Receiver registered with this activity to get the response from FetchAddressIntentService.
*/
private AddressResultReceiver mResultReceiver;
/**
* Displays the location address.
*/
private TextView selectManually;
private TextView mLocationAddressTextView;
/**
* Visible while the address is being fetched.
*/
private ProgressBar mProgressBar;
/**
* Kicks off the request to fetch an address when pressed.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.location_fetch);
mResultReceiver = new AddressResultReceiver(new Handler());
mProgressBar = findViewById(R.id.progress_bar2);
selectManually= findViewById(R.id.select_manually);
// Set defaults, then update using values stored in the Bundle.
mAddressRequested = false;
mAddressOutput = "";
updateValuesFromBundle(savedInstanceState);
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
if (!checkPermissions()) {
requestPermissions();
} else {
getAddress();
}
}
@Override
public void onStart() {
super.onStart();
updateUIWidgets();
}
/**
* Updates fields based on data stored in the bundle.
*/
private void updateValuesFromBundle(Bundle savedInstanceState) {
if (savedInstanceState != null) {
// Check savedInstanceState to see if the address was previously requested.
if (savedInstanceState.keySet().contains(ADDRESS_REQUESTED_KEY)) {
mAddressRequested = savedInstanceState.getBoolean(ADDRESS_REQUESTED_KEY);
}
// Check savedInstanceState to see if the location address string was previously found
// and stored in the Bundle. If it was found, display the address string in the UI.
if (savedInstanceState.keySet().contains(LOCATION_ADDRESS_KEY)) {
mAddressOutput = savedInstanceState.getString(LOCATION_ADDRESS_KEY);
Intent intent = new Intent(getBaseContext(), LocationShow.class);
intent.putExtra("addressOutput", mAddressOutput);
startActivity(intent);
}
}
}
/**
* Runs when user clicks the Fetch Address button.
/**
* Creates an intent, adds location data to it as an extra, and starts the intent service for
* fetching an address.
*/
private void startIntentService() {
// Create an intent for passing to the intent service responsible for fetching the address.
Intent intent = new Intent(this, FetchAddressIntentService.class);
// Pass the result receiver as an extra to the service.
intent.putExtra(Constants.RECEIVER, mResultReceiver);
// Pass the location data as an extra to the service.
intent.putExtra(Constants.LOCATION_DATA_EXTRA, mLastLocation);
// Start the service. If the service isn't already running, it is instantiated and started
// (creating a process for it if needed); if it is running then it remains running. The
// service kills itself automatically once all intents are processed.
startService(intent);
}
/**
* Gets the address for the last known location.
*/
@SuppressWarnings("MissingPermission")
private void getAddress() {
mFusedLocationClient.getLastLocation()
.addOnSuccessListener(this, new OnSuccessListener<Location>() {
@Override
public void onSuccess(Location location) {
if (location == null) {
Log.w(TAG, "onSuccess:null");
mAddressRequested=false;
updateUIWidgets();
return;
}
mLastLocation = location;
// Determine whether a Geocoder is available.
if (!Geocoder.isPresent()) {
showSnackbar(getString(R.string.no_geocoder_available));
mAddressRequested=false;
updateUIWidgets();
return;
}
// If the user pressed the fetch address button before we had the location,
// this will be set to true indicating that we should kick off the intent
// service after fetching the location.
mAddressRequested=true;
if (mAddressRequested) {
startIntentService();
return;
}
updateUIWidgets();
}
})
.addOnFailureListener(this, new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.w(TAG, "getLastLocation:onFailure", e);
mAddressRequested=false;
updateUIWidgets();
}
});
}
/**
* Updates the address in the UI.
*/
/**
* Toggles the visibility of the progress bar. Enables or disables the Fetch Address button.
*/
private void updateUIWidgets() {
mAddressRequested=true;
if (mAddressRequested) {
mProgressBar.setVisibility(ProgressBar.VISIBLE);
selectManually.setVisibility(TextView.GONE);
} else {
mProgressBar.setVisibility(ProgressBar.GONE);
selectManually.setVisibility(TextView.VISIBLE);
}
}
/**
* Shows a toast with the given text.
*/
private void showToast(String text) {
Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
}
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save whether the address has been requested.
savedInstanceState.putBoolean(ADDRESS_REQUESTED_KEY, mAddressRequested);
// Save the address string.
savedInstanceState.putString(LOCATION_ADDRESS_KEY, mAddressOutput);
super.onSaveInstanceState(savedInstanceState);
}
/**
* Receiver for data sent from FetchAddressIntentService.
*/
private class AddressResultReceiver extends ResultReceiver {
AddressResultReceiver(Handler handler) {
super(handler);
}
/**
* Receives data sent from FetchAddressIntentService and updates the UI in MainActivity.
*/
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
// Display the address string or an error message sent from the intent service.
mAddressOutput = resultData.getString(Constants.RESULT_DATA_KEY);
Intent intent = new Intent(getBaseContext(), LocationShow.class);
intent.putExtra("addressOutput", mAddressOutput);
startActivity(intent);
// Show a toast message if an address was found.
if (resultCode == Constants.SUCCESS_RESULT) {
showToast(getString(R.string.address_found));
}
// Reset. Enable the Fetch Address button and stop showing the progress bar.
}
}
/**
* Shows a {@link Snackbar} using {@code text}.
*
* @param text The Snackbar text.
*/
private void showSnackbar(final String text) {
View container = findViewById(android.R.id.content);
if (container != null) {
Snackbar.make(container, text, Snackbar.LENGTH_LONG).show();
}
}
/**
* Shows a {@link Snackbar}.
*
* @param mainTextStringId The id for the string resource for the Snackbar text.
* @param actionStringId The text of the action item.
* @param listener The listener associated with the Snackbar action.
*/
private void showSnackbar(final int mainTextStringId, final int actionStringId,
View.OnClickListener listener) {
Snackbar.make(findViewById(android.R.id.content),
getString(mainTextStringId),
Snackbar.LENGTH_INDEFINITE)
.setAction(getString(actionStringId), listener).show();
}
/**
* Return the current state of the permissions needed.
*/
private boolean checkPermissions() {
int permissionState = ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION);
return permissionState == PackageManager.PERMISSION_GRANTED;
}
private void requestPermissions() {
boolean shouldProvideRationale =
ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_FINE_LOCATION);
// Provide an additional rationale to the user. This would happen if the user denied the
// request previously, but didn't check the "Don't ask again" checkbox.
if (shouldProvideRationale) {
Log.i(TAG, "Displaying permission rationale to provide additional context.");
showSnackbar(R.string.permission_rationale, android.R.string.ok,
new View.OnClickListener() {
@Override
public void onClick(View view) {
// Request permission
ActivityCompat.requestPermissions(Main2Activity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_PERMISSIONS_REQUEST_CODE);
}
});
} else {
Log.i(TAG, "Requesting permission");
// Request permission. It's possible this can be auto answered if device policy
// sets the permission in a given state or the user denied the permission
// previously and checked "Never ask again".
ActivityCompat.requestPermissions(Main2Activity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_PERMISSIONS_REQUEST_CODE);
}
}
/**
* Callback received when a permissions request has been completed.
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
Log.i(TAG, "onRequestPermissionResult");
if (requestCode == REQUEST_PERMISSIONS_REQUEST_CODE) {
if (grantResults.length <= 0) {
// If user interaction was interrupted, the permission request is cancelled and you
// receive empty arrays.
Log.i(TAG, "User interaction was cancelled.");
} else if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission granted.
getAddress();
} else {
// Permission denied.
// Notify the user via a SnackBar that they have rejected a core permission for the
// app, which makes the Activity useless. In a real app, core permissions would
// typically be best requested during a welcome-screen flow.
// Additionally, it is important to remember that a permission might have been
// rejected without asking the user for permission (device policy or "Never ask
// again" prompts). Therefore, a user interface affordance is typically implemented
// when permissions are denied. Otherwise, your app could appear unresponsive to
// touches or interactions which have required permissions.
showSnackbar(R.string.permission_denied_explanation, R.string.settings,
new View.OnClickListener() {
@Override
public void onClick(View view) {
// Build intent that displays the App settings screen.
Intent intent = new Intent();
intent.setAction(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package",
BuildConfig.APPLICATION_ID, null);
intent.setData(uri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
});
}
}
}
}
FetchAddressIntentService
public class FetchAddressIntentService extends IntentService {
private static final String TAG = "FetchAddressIS";
/**
* The receiver where results are forwarded from this service.
*/
private ResultReceiver mReceiver;
/**
* This constructor is required, and calls the super IntentService(String)
* constructor with the name for a worker thread.
*/
public FetchAddressIntentService() {
// Use the TAG to name the worker thread.
super(TAG);
}
/**
* Tries to get the location address using a Geocoder. If successful, sends an address to a
* result receiver. If unsuccessful, sends an error message instead.
* Note: We define a {@link ResultReceiver} in * MainActivity to process content
* sent from this service.
*
* This service calls this method from the default worker thread with the intent that started
* the service. When this method returns, the service automatically stops.
*/
@Override
protected void onHandleIntent(Intent intent) {
String errorMessage = "";
mReceiver = intent.getParcelableExtra(Constants.RECEIVER);
// Check if receiver was properly registered.
if (mReceiver == null) {
Log.wtf(TAG, "No receiver received. There is nowhere to send the results.");
return;
}
// Get the location passed to this service through an extra.
Location location = intent.getParcelableExtra(Constants.LOCATION_DATA_EXTRA);
// Make sure that the location data was really sent over through an extra. If it wasn't,
// send an error error message and return.
if (location == null) {
errorMessage = "no location data provided";
Log.wtf(TAG, errorMessage);
deliverResultToReceiver(Constants.FAILURE_RESULT, errorMessage);
return;
}
// Errors could still arise from using the Geocoder (for example, if there is no
// connectivity, or if the Geocoder is given illegal location data). Or, the Geocoder may
// simply not have an address for a location. In all these cases, we communicate with the
// receiver using a resultCode indicating failure. If an address is found, we use a
// resultCode indicating success.
// The Geocoder used in this sample. The Geocoder's responses are localized for the given
// Locale, which represents a specific geographical or linguistic region. Locales are used
// to alter the presentation of information such as numbers or dates to suit the conventions
// in the region they describe.
Geocoder geocoder = new Geocoder(this, Locale.getDefault());
// Address found using the Geocoder.
List<Address> addresses = null;
try {
// Using getFromLocation() returns an array of Addresses for the area immediately
// surroungetString(R.string.invalid_lat_long_used)ding the given latitude and longitude. The results are a best guess and are
// not guaranteed to be accurate.
addresses = geocoder.getFromLocation(
location.getLatitude(),
location.getLongitude(),
// In this sample, we get just a single address.
1);
} catch (IOException ioException) {
// Catch network or other I/O problems.
errorMessage = "service not available";
Log.e(TAG, errorMessage, ioException);
} catch (IllegalArgumentException illegalArgumentException) {
// Catch invalid latitude or longitude values.
errorMessage ="invalid lat and long" ;
Log.e(TAG, errorMessage + ". " +
"Latitude = " + location.getLatitude() +
", Longitude = " + location.getLongitude(), illegalArgumentException);
}
// Handle case where no address was found.
if (addresses == null || addresses.size() == 0) {
if (errorMessage.isEmpty()) {
errorMessage = "no address found";
Log.e(TAG, errorMessage);
}
deliverResultToReceiver(Constants.FAILURE_RESULT, errorMessage);
} else {
Address address = addresses.get(0);
ArrayList<String> addressFragments = new ArrayList<>();
// Fetch the address lines using {@code getAddressLine},
// join them, and send them to the thread. The {@link android.location.address}
// class provides other options for fetching address details that you may prefer
// to use. Here are some examples:
// getLocality() ("Mountain View", for example)
// getAdminArea() ("CA", for example)
// getPostalCode() ("94043", for example)
// getCountryCode() ("US", for example)
// getCountryName() ("United States", for example)
for(int i = 0; i <= address.getMaxAddressLineIndex(); i++) {
addressFragments.add(address.getSubLocality());
}
Log.i(TAG, "address found");
deliverResultToReceiver(Constants.SUCCESS_RESULT,
TextUtils.join(System.getProperty("line.separator"), addressFragments));
}
}
/**
* Sends a resultCode and message to the receiver.
*/
private void deliverResultToReceiver(int resultCode, String message) {
Bundle bundle = new Bundle();
bundle.putString(Constants.RESULT_DATA_KEY, message);
mReceiver.send(resultCode, bundle);
}
}
LocationShow
public class LocationShow extends AppCompatActivity {
TextView t1;
String output,output2;
private static final String ADDRESS_REQUESTED_KEY = "address-request-pending";
private static final String LOCATION_ADDRESS_KEY = "location-address";
String mAddressOutput;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
t1=findViewById(R.id.place2);
output = getIntent().getStringExtra("addressOutput");
output2 = getIntent().getStringExtra("addressOutput2");
showAddress(output2);
}
private void showAddress(String place) {
t1.setText(place);
}
}
常量
final class Constants {
static final int SUCCESS_RESULT = 0;
static final int FAILURE_RESULT = 1;
private static final String PACKAGE_NAME =
"com.google.android.gms.location.sample.locationaddress";
static final String RECEIVER = PACKAGE_NAME + ".RECEIVER";
static final String RESULT_DATA_KEY = PACKAGE_NAME + ".RESULT_DATA_KEY";
static final String LOCATION_DATA_EXTRA = PACKAGE_NAME + ".LOCATION_DATA_EXTRA";
}
这是日志输出
07-16 23:36:43.553 16544-16544/? E/android.os.Debug: failed to load memtrack module: -2
07-16 23:36:43.948 16555-16555 /? E / memtrack:无法加载memtrack模块(无此文件或目录) 07-16 23:36:43.948 16555-16555 /? E / android.os.Debug:无法加载memtrack模块:-2 07-16 23:36:44.440 16566-16566 /? E / memtrack:无法加载memtrack模块(无此文件或目录) 07-16 23:36:44.440 16566-16566 /? E / android.os.Debug:无法加载memtrack模块:-2 07-16 23:36:44.935 16577-16577 /? E / memtrack:无法加载memtrack模块(无此文件或目录) 07-16 23:36:44.935 16577-16577 /? E / android.os.Debug:无法加载memtrack模块:-2 07-16 23:36:45.641 16588-16588 /? E / memtrack:无法加载memtrack模块(无此文件或目录) 07-16 23:36:45.641 16588-16588 /? E / android.os.Debug:无法加载memtrack模块:-2 07-16 23:36:46.052 16599-16599 /? E / memtrack:无法加载memtrack模块(无此文件或目录) 07-16 23:36:46.052 16599-16599 /? E / android.os.Debug:无法加载memtrack模块:-2 07-16 23:36:46.241 16608-16612 /?电子/艺术:无法向调试器发送回复:管道损坏 07-16 23:36:46.772 1322-1322 /? E /已安装:无法打开目录/data/app/vmdl1055021888.tmp:无此类文件或目录 07-16 23:36:46.952 1990-13324 / com.google.android.gms.persistent E / NetworkScheduler:提供了无法识别的操作:android.intent.action.PACKAGE_REMOVED 07-16 23:36:47.363 16660-16660 /? E / memtrack:无法加载memtrack模块(无此文件或目录) 07-16 23:36:47.363 16660-16660 /? E / android.os.Debug:无法加载memtrack模块:-2 2016年7月16日23:36:47.682 / com.android.launcher3 E /曲面:getSlotFromBufferLocked:未知缓冲区:0x7f4388d4cc80 07-16 23:36:47.724 16699-16699 /? E / dex2oat:无法创建燕麦文件:/data/dalvik-cache/x86_64/data@app@com.example.user.practice-1@split_lib_dependencies_apk.apk@classes.dex:权限被拒绝 07-16 23:36:47.936 16717-16717 /? E / dex2oat:无法创建燕麦文件:/data/dalvik-cache/x86_64/data@app@com.example.user.practice-1@split_lib_slice_0_apk.apk@classes.dex:权限被拒绝 07-16 23:36:47.995 16722-16722 /? E / dex2oat:无法创建燕麦文件:/data/dalvik-cache/x86_64/data@app@com.example.user.practice-1@split_lib_slice_1_apk.apk@classes.dex:权限被拒绝 07-16 23:36:48.044 16725-16725 /? E / dex2oat:无法创建燕麦文件:/data/dalvik-cache/x86_64/data@app@com.example.user.practice-1@split_lib_slice_2_apk.apk@classes.dex:权限被拒绝 07-16 23:36:48.079 16728-16728 /? E / dex2oat:无法创建燕麦文件:/data/dalvik-cache/x86_64/data@app@com.example.user.practice-1@split_lib_slice_3_apk.apk@classes.dex:权限被拒绝 07-16 23:36:48.122 16732-16732 /? E / dex2oat:无法创建燕麦文件:/data/dalvik-cache/x86_64/data@app@com.example.user.practice-1@split_lib_slice_4_apk.apk@classes.dex:权限被拒绝 07-16 23:36:48.149 16736-16736 /? E / dex2oat:无法创建燕麦文件:/data/dalvik-cache/x86_64/data@app@com.example.user.practice-1@split_lib_slice_5_apk.apk@classes.dex:权限被拒绝 07-16 23:36:48.185 16739-16739 /? E / dex2oat:无法创建燕麦文件:/data/dalvik-cache/x86_64/data@app@com.example.user.practice-1@split_lib_slice_6_apk.apk@classes.dex:权限被拒绝 07-16 23:36:48.219 16743-16743 /? E / dex2oat:无法创建燕麦文件:/data/dalvik-cache/x86_64/data@app@com.example.user.practice-1@split_lib_slice_7_apk.apk@classes.dex:权限被拒绝 07-16 23:36:48.249 16629-16729 /? E / ActivityThread:无法找到com.google.android.partnersetup.rlzappprovider的提供商信息 07-16 23:36:48.259 16746-16746 /? E / dex2oat:无法创建燕麦文件:/data/dalvik-cache/x86_64/data@app@com.example.user.practice-1@split_lib_slice_8_apk.apk@classes.dex:权限被拒绝 07-16 23:36:48.299 16750-16750 /? E / dex2oat:无法创建燕麦文件:/data/dalvik-cache/x86_64/data@app@com.example.user.practice-1@split_lib_slice_9_apk.apk@classes.dex:权限被拒绝 07-16 23:36:48.817 1226-1269 /? E / SurfaceFlinger:必须将ro.sf.lcd_density定义为构建属性
这些是我用来显示应用程序中当前用户位置的活动。这些活动之前运行良好,但现在只显示进度条,什么也没有发生。
答案 0 :(得分:0)
Google刚刚对其映射API进行了一些重大更改。没有某种日志输出,很难说会发生什么情况,但是如果您没有更改代码,我将检查与映射密钥关联的帐户,看看是否需要向该帐户添加信用卡。此处更多信息:https://developers.google.com/maps/billing/important-updates