辅导Android Project、辅导Java andriod 编程语言
- 首页 >> Java编程Convert Old Android Project for Android X (in build.gradle)
1.Change CompileSDK to minimum of 28
2.Change TargetSDK to minimum of 28
3.Change Support Library version to “com.android.support:appcompat-v7:28.0.0”
4.Do “Sync Now” for Build.gradle to apply new settings
5.Choose Refactor Migrate to Android X menu, and then click Migrate after unchecking “Backup project as Zip file”
6.Click “Do Refactor” in the “Refactor Preview” summary shown in bottom area of Android Studio
Set up Google Play services. (Not needed if already installed)
Install the Google Repository and update the Android SDK Manager:
1.Open Android Studio.
2.Select Tools > Android > SDK Manager.
3.Select the SDK Tools tab.
4.Expand Support Repository, select Google Repository, and click OK.
Now you can include Google Play services packages in your app.
To add Google Play services to your project, add the following line of code to the dependencies section in your app-level build.gradle (Module: app) file:
implementation 'com.google.android.gms:play-services-location:XX.X.X'
Replace XX.X.X with the latest version number for Google Play services, for example 11.0.2. Android Studio will let you know if you need to update it. For more information and the latest version number, see Add Google Play Services to Your Project.
Set location permission in the manifest
Using the Location API requires permission from the user. Android offers two location permissions:
ACCESS_COARSE_LOCATION
ACCESS_FINE_LOCATION
The permission you choose determines the accuracy of the location returned by the API. For this lesson, use the ACCESS_FINE_LOCATION permission, because you want the most accurate location information possible.
1.Add the following element to your manifest file, above the <application> element:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
2.2 Request permission at runtime
Starting with Android 6.0 (API level 23), it's not always enough to include a permission statement in the manifest. For "dangerous" permissions, you also have to request permission programmatically, at runtime.
Note: Dangerous permissions cover areas where the app wants to access, use or change data or resources that involve the user's private information, or could potentially affect the user's stored data or the operation of other apps.
To request location permission at runtime:
1.Create an OnClickListener for the Get Location button in onCreate() in MainActivity.
2.Create a method stub called getLocation() that takes no arguments and doesn't return anything. Invoke the getLocation() method from the button's onClick() method.
3.In the getLocation() method, check for the ACCESS_FINE_LOCATION permission.
If the permission has not been granted, request it.
If the permission has been granted, display a message in the logs.
For information on runtime permissions, see Requesting Permissions at Run Time.
private void getLocation() {
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]
{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_LOCATION_PERMISSION);
} else {
Log.d("TAG", "getLocation: permissions granted");
}
}
4.In your MainActivity class, define an integer constant REQUEST_LOCATION_PERMISSION. This constant is used to identify the permission request when the results come back in the onRequestPemissionsResult() method. It can be any integer greater than 0.
5.Override the onRequestPermissionsResult() method. If the permission was granted, call getLocation(). Otherwise, show a Toast saying that the permission was denied.
@Override
public void onRequestPermissionsResult(int requestCode,
@NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
case REQUEST_LOCATION_PERMISSION:
// If the permission is granted, get the location,
// otherwise, show a Toast
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
getLocation();
} else {
Toast.makeText(this,
R.string.location_permission_denied,
Toast.LENGTH_SHORT).show();
}
break;
}
}
Use Alt + Enter key to auto import missing libraries. Add below string resource in String.xml file
<string name="location_permission_denied">Location permissions denied,
please enable the permissions to use this app.
</string>
6.Run the app. Clicking the button requests permission from the user. If permission is granted, you see a log statement in the console.
After you grant permission, subsequent clicks on the Get Location button have no effect. Because you already granted permission, the app doesn't need to ask for permission again (unless the user manually revokes it in the Settings app), even if you close and restart the app.
Get the last known location
The getLastLocation() method doesn't actually make a location request. It simply returns the location most recently obtained by the FusedLocationProviderClient class.
If no location has been obtained since the device was restarted, the getLastLocation() method may return null. Usually, the getLastLocation() method returns a Location object that contains a timestamp of when this location was obtained.
To get the last known location:
1.In strings.xml, add a string resource called location_text. Use location_text to display the latitude, longitude, and timestamp of the last known location.
<string name="location_text">"Latitude: %1$.4f \n Longitude: %2$.4f
\n Timestamp: %3$tr"</string>
Note: If you aren't familiar with string replacement and formatting, see Formatting and Styling and the Formatter documentation.
2.In your MainActivity class, create a member variable of the Location type called mLastLocation.
3.Find the location TextView by ID (textview_location) in onCreate(). Assign the TextView to a member variable called mLocationTextView.
4.Create a member variable of the FusedLocationProviderClient type called mFusedLocationClient.
5.Initialize mFusedLocationClient in onCreate() with the following code:
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
The getLastLocation() method returns a Task that results in a Location object (after the Task's onSuccess() callback method is called, signifying that the Task was successful).
Retrieve the latitude and longitude coordinates of a geographic location from the resulting Location object:
1.Replace the log statement in the getLocation() method with the following code snippet. The code obtains the device's most recent location and assigns it to mLastLocation.
If the returned location is not null, set the TextView to show the coordinates and time stamp of the Location object.
If the location returned is null, the fused location provider has not obtained a location since the device was restarted. Display a message in the TextView that says that the location is not available.
mFusedLocationClient.getLastLocation().addOnSuccessListener(
new OnSuccessListener<Location>() {
@Override
public void onSuccess(Location location) {
if (location != null) {
mLastLocation = location;
mLocationTextView.setText(
getString(R.string.location_text,
mLastLocation.getLatitude(),
mLastLocation.getLongitude(),
mLastLocation.getTime()));
} else {
mLocationTextView.setText(R.string.no_location);
}
}
});
2.Run the app. You now see the latest location that is stored in the fused location provider.
Testing location on an emulator (Not needed for physical device)
If you test your app on an emulator, use a system image that supports Google APIs or Google Play:
1.In Android Studio, create a new virtual device and select hardware for it.
2.In the System Image dialog, choose an image that says "Google APIs" or "Google Play" in the Target column.
To update the fused location provider on an emulator:
1.The emulator appears on your screen with a vertical menu to the right of the virtual device. To access emulator options, click the ... icon at the bottom of this vertical menu.
2.Click Location.
3.Enter or change the coordinates in the Longitude and Latitude fields.
4.Click Send to update the fused location provider.
Clicking Send does not affect the location returned by getLastLocation(), because getLastLocation() uses a local cache that the emulator tools do not update.
When you test the app on an emulator, the getLastLocation() method might return null, because the fused location provider doesn't update the location cache after the device is restarted. If getLastLocation() returns null unexpectedly:
1.Start the Google Maps app and accept the terms and conditions, if you haven't already.
2.Use the steps above to update the fused location provider. Google Maps will force the local cache to update.
3.Go back to your app and click the Get Location button. The app updates with the new location.
Get the location as an address
Your app displays the device's most recent location, which usually corresponds to its current location, using latitude and longitude coordinates. Although latitude and longitude are useful for calculating distance or displaying a map position, in many cases the address of the location is more useful. For example, if you want to let your users know where they are or what is close by, a street address is more meaningful than the geographic coordinates of the location.
The process of converting from latitude/longitude to a physical address is called reverse geocoding. The getFromLocation() method provided by the Geocoder class accepts a latitude and longitude and returns a list of addresses. The method is synchronous and requires a network connection. It may take a long time to do its work, so do not call it from the main user interface (UI) thread of your app.
Convert the location into an address string
In this step, you add code in onSucess() method so that it converts the obtained Location object into an address string, if possible. If there is a problem, you show an error message.
1.Create a Geocoder object. This class handles both geocoding (converting from an address into coordinates) and reverse geocoding:
Geocoder geocoder = new Geocoder(mContext,
Locale.getDefault());
2.Obtain a Location object. The passed-in parameter is a Java varargs argument that can contain any number of objects. In this case we only pass in one Location object, so the desired object is the first item in the varargs array:
Location location = params[0];
3.Create an empty List of Address objects, which will be filled with the address obtained from the Geocoder. Create an empty String to hold the final result, which will be either the address or an error:
List<Address> addresses = null;
String resultMessage = "";
4.You are now ready to start the geocoding process. Open up a try block and use the following code to attempt to obtain a list of addresses from the Location object. The third parameter specifies the maximum number of addresses that you want to read. In this case you only want a single address:
try {
addresses = geocoder.getFromLocation(
location.getLatitude(),
location.getLongitude(),
// In this sample, get just a single address
1);
}
5.Open a catch block to catch IOException exceptions that are thrown if there is a network error or a problem with the Geocoder service. In this catch block, set the resultMessage to an error message that says "Service not available." Log the error and result message:
catch (IOException ioException) {
// Catch network or other I/O problems
resultMessage = mContext
.getString(R.string.service_not_available);
Log.e(TAG, resultMessage, ioException);
}
6.Open another catch block to catch IllegalArgumentException exceptions. Set the resultMessage to a string that says "Invalid coordinates were supplied to the Geocoder," and log the error and result message:
catch (IllegalArgumentException illegalArgumentException) {
// Catch invalid latitude or longitude values
resultMessage =getApplicationContext()
.getString(R.string.invalid_lat_long_used);
Log.e(TAG, resultMessage + ". " +
"Latitude = " + location.getLatitude() +
", Longitude = " +
location.getLongitude(), illegalArgumentException);
}
7.You need to catch the case where Geocoder is not able to find the address for the given coordinates. In the try block, check the address list and the resultMessage string. If the address list is empty or null and the resultMessage string is empty, then set the resultMessage to "No address found" and log the error:
if (addresses == null || addresses.size() == 0) {
if (resultMessage.isEmpty()) {
resultMessage = getApplicationContext()
.getString(R.string.no_address_found);
Log.e(TAG, resultMessage);
}
}
8.If the address list is not empty or null, the reverse geocode was successful.
The next step is to read the first address into a string, line by line:
1.Create an empty ArrayList of Strings.
2.Iterate over the List of Address objects and read them into the new ArrayList line by line.
3.Use the TextUtils.join() method to convert the list into a string. Use the \n character to separate each line with the new-line character:
Here is the code:
else {
// If an address is found, read it into resultMessage
Address address = addresses.get(0);
ArrayList<String> addressParts = new ArrayList<>();
// Fetch the address lines using getAddressLine,
// join them, and send them to the thread
for (int i = 0; i <= address.getMaxAddressLineIndex(); i++) {
addressParts.add(address.getAddressLine(i));
}
resultMessage = TextUtils.join("\n", addressParts);
}
4.At the bottom of doInBackground() method, return the resultMessage object.
3.3 Display the result in TextView
1.In this code, updated the TextView with the resulting address and the current time:
// Update the UI
mLocationTextView.setText(resultMessage);
2.Run the app. After briefly loading, the app displays the location address in the TextView.