【发布时间】:2018-08-18 16:17:11
【问题描述】:
当我在 Android 设备上运行应用程序时,我在我的应用程序中使用 Google 地图,显示左下方带有 Google 徽标的白屏。但是当我在模拟器上运行它时,可以完美地显示地图
这里是 MapsActivity.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>
这里是 MapsActivity.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;
}
}
这里是 Android Manifest.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>
这里我附上了两个条件的截图
- 当应用在 Android 设备上运行时:设备映像
- 当应用在模拟器上运行时:模拟器图像
这是在模拟器中使用 Signed Release 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
我已启用“Google Maps Android API”。并且 API 密钥存在。 但是,我没有找到“Google Maps Android API v2”。和“Google Maps Android API”一样吗?
【问题讨论】:
-
设备上是否安装了 Google Play 服务?
-
不是这一定是答案,但是您是否在 Android 清单 XML 文件中声明了您的 Google API 密钥?
-
@ArthurAttout Play 服务已安装
-
@TimBiegeleisen 谢谢,我在 Android Manifest 中声明了 API KEY 并尝试重新生成新的 API 密钥。但错误未解决
-
发布你的 manifest.xml
标签: android google-maps firebase