当我在Android设备上运行时,我正在我的应用程序中使用谷歌地图,显示左下角有谷歌标志的白屏。但是当我在模拟器上运行它时,可以完美地显示地图
这是地图活动.xml
<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"
xmlns:app="http://schemas.android.com/apk/res-auto">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:id="@+id/appBarLayout">
<include layout="@layout/main_app_bar_layout"
android:id="@+id/main_page_toolbar" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.DrawerLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/drawerLayout"
android:layout_marginTop="@dimen/cast_libraries_material_featurehighlight_inner_radius">
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_below="@id/main_page_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MapsActivity"
tools:ignore="NotSibling" />
<android.support.design.widget.NavigationView
android:id="@+id/navigation_home"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:menu="@menu/navigation_menu"
android:layout_gravity="start"
app:headerLayout="@layout/navigation_header_layout">
</android.support.design.widget.NavigationView>
</android.support.v4.widget.DrawerLayout>
</RelativeLayout>
这是地图活动.java
public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener {
// toolbar instance
private android.support.v7.widget.Toolbar mToolbar;
RelativeLayout rootLayout;
private DrawerLayout mDrawerlayout;
private ActionBarDrawerToggle mToggle;
private NavigationView mNavigationView;
//Request code
private static final int PERMISSION_REQUEST_CODE = 1998;
private static final int PLAY_SERVICES_REQUEST_CODE = 1999;
//Google APi client
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
private Location mLastLocation;
Marker mCurrentMarker;
private GoogleMap mMap;
double lattitude, longitude;
//Map intervals
private static int UPDATE_INTERVAL = 5000;
private static int FASTEST_INTERVAL = 3000;
private static int DISPLACEMENT = 10;
//Firebase
DatabaseReference mUserDatabase, locationDatabaseRef;
private FirebaseAuth mAuth;
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase));
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
//Custom Toolbar
mToolbar = (android.support.v7.widget.Toolbar) findViewById(R.id.main_page_toolbar);
setSupportActionBar(mToolbar);
getSupportActionBar().setTitle("Control Child");
mDrawerlayout = (DrawerLayout) findViewById(R.id.drawerLayout);
mToggle = new ActionBarDrawerToggle(this, mDrawerlayout, R.string.open, R.string.close);
mDrawerlayout.addDrawerListener(mToggle);
mToggle.syncState();
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// Firebase initialization
mUserDatabase = FirebaseDatabase.getInstance().getReference().child("Users");
locationDatabaseRef = FirebaseDatabase.getInstance().getReference().child("Locations");
mNavigationView = (NavigationView) findViewById(R.id.navigation_home);
mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
if (menuItem.getItemId() == R.id.navigationAccount) {
Intent profileIntent = new Intent(MapsActivity.this, ProfileActivity.class);
startActivity(profileIntent);
mDrawerlayout.closeDrawers();
}
if (menuItem.getItemId() == R.id.navigationSettings) {
Intent settingsIntent = new Intent(MapsActivity.this, SettingsActivity.class);
startActivity(settingsIntent);
mDrawerlayout.closeDrawers();
}
if (menuItem.getItemId() == R.id.navigationContact) {
}
return false;
}
});
mAuth = FirebaseAuth.getInstance();
//set contentView
CalligraphyConfig.initDefault(new CalligraphyConfig.Builder()
.setDefaultFontPath("fonts/Arkhip_font.ttf")
.setFontAttrId(R.attr.fontPath)
.build()
);
setUpLocation();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_CODE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (checkPlayServices()) {
buildGoogleApiClient();
createLocationRequest();
displayLocation();
}
}
break;
}
}
private void setUpLocation() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
requestRuntimePermission();
} else {
if (checkPlayServices()) {
buildGoogleApiClient();
createLocationRequest();
displayLocation();
}
}
}
private void displayLocation() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mLastLocation != null) {
lattitude = mLastLocation.getLatitude();
longitude = mLastLocation.getLongitude();
//Updating to firebase
locationDatabaseRef.child(mAuth.getCurrentUser().getUid())
.setValue(new Tracking(mAuth.getCurrentUser().getEmail(),
mAuth.getCurrentUser().getUid(),
String.valueOf(mLastLocation.getLatitude()),
String.valueOf(mLastLocation.getLongitude())));
mMap.clear();
mCurrentMarker = mMap.addMarker(new MarkerOptions()
.position(new LatLng(lattitude, longitude))
.title("You are Here"));
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(lattitude, longitude), 12.02f));
/*if(!hasAnimated){
hasAnimated = true;
}else {
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(lattitude, longitude), 12.02f));
}*/
}
}
private void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setSmallestDisplacement(DISPLACEMENT);
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
private boolean checkPlayServices() {
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
GooglePlayServicesUtil.getErrorDialog(resultCode, this, PLAY_SERVICES_REQUEST_CODE).show();
} else {
Toast.makeText(this, "This device is not supported", Toast.LENGTH_SHORT).show();
finish();
}
return false;
}
return true;
}
private void requestRuntimePermission() {
ActivityCompat.requestPermissions(this, new String[]{
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION
}, PERMISSION_REQUEST_CODE);
}
private void startLocationUpdates() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.getUiSettings().setMapToolbarEnabled(false);
mMap.getUiSettings().setMyLocationButtonEnabled(true);
}
@Override
public void onConnected(@Nullable Bundle bundle) {
displayLocation();
startLocationUpdates();
}
@Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
@Override
public void onLocationChanged(Location location) {
mLastLocation = location;
displayLocation();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.main_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
if (item.getItemId() == R.id.connect_item) {
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
dialog.setTitle("Make Connection");
dialog.setMessage("Please use ID shown in profile");
LayoutInflater inflater = LayoutInflater.from(this);
final View connect_layout = inflater.inflate(R.layout.connect_layout, null);
final MaterialEditText connectID = connect_layout.findViewById(R.id.connect_id);
dialog.setView(connect_layout);
dialog.setPositiveButton("Connect", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
//validation
if (TextUtils.isEmpty(connectID.getText().toString())) {
Snackbar.make(rootLayout, "Please enter ID", Snackbar.LENGTH_SHORT)
.show();
return;
}
mUserDatabase.orderByChild("uniqueID").equalTo(connectID.getText().toString())
.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
// giving connected user data Log.d("QueryLog",dataSnapshot.getValue().toString());
// Getting lattitude and longitude
//Log.d("userLoc", dataSnapshot.getValue().);
//Log.d("LocationIser", locationDatabaseRef.child(dataSnapshot.getValue().toString()) + "/" + );
Toast.makeText(MapsActivity.this, "Yo ! Connected Successfully", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MapsActivity.this, "User Not Exist", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
});
// this is cancel btn for dialog
dialog.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
dialog.show();
}
// Logout is here
if (item.getItemId() == R.id.logout) {
FirebaseAuth.getInstance().signOut();
Intent MainIntent = new Intent(MapsActivity.this, StartActivity.class);
startActivity(MainIntent);
finish();
}
if (mToggle.onOptionsItemSelected(item)) {
return true;
}
return true;
}
}
这是安卓清单.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="MY_PACKAGE_NAME">
<!--
The ACCESS_COARSE/FINE_LOCATION permissions are not required to use
Google Maps Android API v2, but you must specify either coarse or fine
location permissions for the 'MyLocation' functionality.
-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".StartActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!--
The API key for Google Maps-based APIs is defined as a string resource.
(See the file "res/values/google_maps_api.xml").
Note that the API key is linked to the encryption key used to sign the APK.
You need a different API key for each encryption key, including the release key that is used to
sign the APK for publishing.
You can define the keys for the debug and release targets in src/debug/ and src/release/.
-->
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="@string/google_maps_key" />
<activity
android:name=".MapsActivity"
android:label="@string/title_activity_maps" />
<activity
android:name=".ProfileActivity"
android:parentActivityName=".MapsActivity"/>
<activity android:name=".SettingsActivity"
android:parentActivityName=".MapsActivity">
</activity>
</application>
</manifest>
在这里,我为这两种情况都附上了两个屏幕截图
- 当应用程序在安卓设备上运行时:设备图像
[设备图像]
- 当应用在模拟器上运行时:模拟器图像
[模拟器图像]
这是在模拟器中使用签名发布 Apk 时的 Logcat 错误:
Google Maps Android API: Authorization failure. Please see https://developers.google.com/maps/documentation/android-api/start for how to correctly set up the map.
Google Maps Android API: In the Google Developer Console (https://console.developers.google.com)
Ensure that the "Google Maps Android API v2" is enabled.
Ensure that the following Android Key exists:
API Key: YOUR_KEY_HERE
我启用了"谷歌地图安卓API"。并且 API 密钥存在。但是,我没有找到"谷歌地图Android API v2"。它和"谷歌地图安卓API"一样吗?
在清单中.xml您必须像这样重命名活动:
android:name="com.project.me.appname.Activitys.MapsActivity"
在谷歌地图 API 仪表板上为签名的 Apk 添加 SHA-1 指纹解决了我的问题。