2016-04-23 97 views
0

我有一個Android應用程序,當在調試模式下運行時,顯示谷歌地圖罰款。但是,在發佈模式下運行(通過單擊左下方的菜單圖標並選擇「生成變體」 - >「發佈」)不會顯示地圖。根據相關帖子中的其他人推薦,將硬編碼的API密鑰放入manifest.xml和google_maps_api.xml中,但仍然無效。嘗試運行發行版時獲取大量錯誤消息。下面是一個示例:谷歌地圖仍然沒有顯示在Android應用程序

04-23 13:31:34.562 10519-10612/? E/b? Authentication failed on the server. 
04-23 13:31:34.563 10519-10612/? E/Google Maps Android API? Authorization failure. Please see https://developers.google.com/maps/documentation/android/start for how to correctly set up the map. 
04-23 13:31:34.568 10519-10612/? E/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: AIzaSyDRtOnaTU1Jc-zxuirnbyNojZn9uasd7eE 
    Android Application (<cert_fingerprint>;<package_name>): 1D:9A:59:E7:67:94:D0:38:80:96:35:E9:A8:90:18:17:3C:56:19:4D;owner.example.com.locator 
04-23 13:31:35.361  263-339/? E/Vold? Failed to find mounted volume for /storage/sdcard1/Android/data/com.apalon.weatherlive.free/cache/ 
04-23 13:31:35.364  263-339/? E/Vold? Failed to find mounted volume for /storage/sdcard1/Android/data/com.apalon.weatherlive.free/cache/ 
04-23 13:31:35.366  263-339/? E/Vold? Failed to find mounted volume for /storage/sdcard1/Android/data/com.apalon.weatherlive.free/cache/ 
04-23 13:31:35.572 10746-10746/? E/helpmorelib#? init 
04-23 13:31:35.583 10746-10746/? A/Adjust? PRODUCTION: Adjust is running in Production mode. Use this setting only for the build that you want to publish. Set the environment to `sandbox` if you want to test your app! 
04-23 13:31:35.720 10746-10787/? E/ActivityThread? Failed to find provider info for com.facebook.katana.provider.AttributionIdProvider 
04-23 13:31:35.832 2119-2137/? E/DataBuffer? Internal data leak within a DataBuffer object detected! Be sure to explicitly call release() on all DataBuffer extending objects when you are done with them. (internal object: [email protected]) 
04-23 13:31:35.832 2119-2137/? E/DataBuffer? Internal data leak within a DataBuffer object detected! Be sure to explicitly call release() on all DataBuffer extending objects when you are done with them. (internal object: [email protected]) 
04-23 13:31:35.832 2119-2137/? E/DataBuffer? Internal data leak within a DataBuffer object detected! Be sure to explicitly call release() on all DataBuffer extending objects when you are done with them. (internal object: [email protected]) 
04-23 13:31:35.833 2119-2137/? E/DataBuffer? Internal data leak within a DataBuffer object detected! Be sure to explicitly call release() on all DataBuffer extending objects when you are done with them. (internal object: [email protected]) 
04-23 13:31:35.833 2119-2137/? E/DataBuffer? Internal data leak within a DataBuffer object detected! Be sure to explicitly call release() on all DataBuffer extending objects when you are done with them. (internal object: [email protected]) 
04-23 13:31:35.915  263-339/? E/Vold? Failed to find mounted volume for /storage/sdcard1/Android/data/com.apalon.weatherlive.free/cache/ 
04-23 13:31:35.957  263-339/? E/Vold? Failed to find mounted volume for /storage/sdcard1/Android/data/com.apalon.weatherlive.free/cache/ 
04-23 13:31:39.320  829-1260/? E/WifiStateMachine? WifiStateMachine CMD_START_SCAN source 10022 txSuccessRate=11.27 rxSuccessRate=10.39 targetRoamBSSID=any RSSI=-29 
04-23 13:31:39.323  829-1260/? E/WifiStateMachine? [1,461,414,699,323 ms] noteScanStartWorkSource{1000} uid 10022 

15666-15666/? E/GMPM? GoogleService failed to initialize, status: 10, Missing an expected resource: 'R.string.google_app_id' for initializing Google services. Possible causes are missing google-services.json or com.google.gms.google-services gradle plugin. 

正如你會看到,如果你看一下下面的代碼,錯誤消息引用了關鍵的是那裏的文件。 此外,我不明白關於缺少資源的最後一條消息(上圖)。

我剛剛構建了應用程序ahain,這次是在調試模式下,它工作得很好,但有趣的是我仍然得到了無數的錯誤消息,幾乎沒有一個對我有任何意義。

在調試模式下構建時,我將以下文件與相同的文件進行了比較,它們看上去完全相同。我應該做什麼的任何想法?謝謝。

AndroidManifest.xml中

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="owner.example.com.locator" > 

    <uses-permission android:name="android.permission.INTERNET" /> 
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 
    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" /> 
    <!-- 
The ACCESS_COARSE/FINE_LOCATION permissions are not required to use 
     Google Maps Android API v2, but are recommended. 
    --> 
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> 
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> 

    <application 
     android:allowBackup="true" 
     android:icon="@mipmap/earthicon" 
     android:label="@string/app_name" 
     android:theme="@style/AppTheme" > 
     <meta-data 
      android:name="com.google.android.gms.version" 
      android:value="@integer/google_play_services_version" /> 
     <meta-data 
      android:name="com.google.android.maps.v2.API_KEY" 
      android:value="AIzaSyDRtOnaTU1Jc-zxuirnbyNojZn9uasd7eE" /> 

     <activity 
      android:name=".LocateMe" 
      android:label="@string/title_activity_locate_me" > 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 

       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 
    </application> 

</manifest> 

主程序文件

package owner.example.com.locator; 

import android.Manifest; 
import android.annotation.TargetApi; 
import android.content.DialogInterface; 
import android.content.pm.PackageManager; 
import android.location.Criteria; 
import android.location.Location; 
import android.location.LocationListener; 
import android.location.LocationManager; 
import android.os.Build; 
import android.support.annotation.NonNull; 
import android.support.v4.app.ActivityCompat; 
import android.support.v4.app.FragmentActivity; 
import android.os.Bundle; 
import android.support.v7.app.AlertDialog; 
import android.widget.Toast; 
import java.math.BigDecimal; 

import com.google.android.gms.maps.CameraUpdateFactory; 
import com.google.android.gms.maps.GoogleMap; 
import com.google.android.gms.maps.OnMapReadyCallback; 
import com.google.android.gms.maps.SupportMapFragment; 
import com.google.android.gms.maps.model.LatLng; 
import com.google.android.gms.maps.model.MarkerOptions; 
//import com.adjust.sdk.Adjust; 
//import com.adjust.sdk.AdjustConfig; 

public class LocateMe extends FragmentActivity implements OnMapReadyCallback, LocationListener { 

    private GoogleMap mMap; 

    private static final int PERMISSION_REQUEST_CODE = 1340; // can be any code you want 
    private LocationManager mLocationManager; 
    Criteria criteria = new Criteria(); 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     //String environment = AdjustConfig.ENVIRONMENT_SANDBOX; 
     setContentView(R.layout.activity_locate_me); 
     mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE); 
     AppData.locman = mLocationManager; 
     //Criteria criteria = new Criteria(); 
     //AppData.crit = criteria; 
     // 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); 
    } 

    @Override 
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) 
    { 
     super.onRequestPermissionsResult(requestCode, permissions, grantResults); 
     switch (requestCode) { 
      case PERMISSION_REQUEST_CODE: 
       if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) 
         != PackageManager.PERMISSION_GRANTED 
         && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) 
         != PackageManager.PERMISSION_GRANTED) 
       { 
        mMap.setMyLocationEnabled(true); 
       } else { 
        AlertDialog dialog = new AlertDialog.Builder(this) 
          .setTitle("Permission needed") 
          .setMessage("Sorry but we need permission to access your location") 
          .setPositiveButton("Grant", new DialogInterface.OnClickListener() { 
           @TargetApi(Build.VERSION_CODES.M) 
           @Override 
           public void onClick(DialogInterface dialog, int which) { 
            String[] permissions = {Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}; 
            requestPermissions(permissions, PERMISSION_REQUEST_CODE); 
           } 
          }).setNegativeButton("Cancel", new DialogInterface.OnClickListener() { 
           @Override 
           public void onClick(DialogInterface dialog, int which) { 
            finish(); 
           } 
          }).create(); 
        dialog.show(); 
       } 
     } 
    } 

    /** 
    * Manipulates the map once available. 
    * This callback is triggered when the map is ready to be used. 
    * This is where we can add markers or lines, add listeners or move the camera. In this case, 
    * we just add a marker near Sydney, Australia. 
    * If Google Play services is not installed on the device, the user will be prompted to install 
    * it inside the SupportMapFragment. This method will only be triggered once the user has 
    * installed Google Play services and returned to the app. 
    */ 
    @TargetApi(Build.VERSION_CODES.M) 
    @Override 
    public void onMapReady(GoogleMap googleMap) { 
     mMap = googleMap; 
     mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID); 
     mMap.getUiSettings().setMyLocationButtonEnabled(true); 
     if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) 
       != PackageManager.PERMISSION_GRANTED 
       && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) 
       != PackageManager.PERMISSION_GRANTED) 
     { 
      String[] permissions = {Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}; 
      requestPermissions(permissions, PERMISSION_REQUEST_CODE); 
      return; 
     } 
     mMap.setMyLocationEnabled(true); 
     Location location = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); 
     AppData.loc = location; 
     if (location != null) { 
      LatLng myLastPosition = new LatLng(location.getLatitude(), location.getLongitude()); 
      mMap.moveCamera(CameraUpdateFactory.newLatLng(myLastPosition)); 
      mMap.animateCamera(CameraUpdateFactory.zoomTo(17)); 

      for (int i=0; i<2; i++) 
      { 
       Toast.makeText(this, 
         getFL(location.getLatitude(),location.getLongitude()) + "\n" 
           + BigDecimal.valueOf(AppData.loc.getLatitude()).setScale(5, 
           BigDecimal.ROUND_HALF_UP).toPlainString() + "  " 
           + BigDecimal.valueOf(AppData.loc.getLongitude()).setScale(5, 
           BigDecimal.ROUND_HALF_UP).toPlainString(), 
         Toast.LENGTH_LONG).show(); 
      }; 
     } 
     mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 10, this); 

     // Location button click listener will show Lat & Long when button clicked 
     mMap.setOnMyLocationButtonClickListener(new GoogleMap.OnMyLocationButtonClickListener() 
     { 
      @Override 
      public boolean onMyLocationButtonClick() 
      { 
       try { 
        AppData.loc = AppData.locman.getLastKnownLocation(AppData.locman.getBestProvider 
          (criteria, false)); 
        Toast.makeText(getApplicationContext(), 
          getFL(AppData.loc.getLatitude(), AppData.loc.getLongitude()) + "\n" 
            + BigDecimal.valueOf(AppData.loc.getLatitude()).setScale(5, 
            BigDecimal.ROUND_HALF_UP).toPlainString() + "  " 
            + BigDecimal.valueOf(AppData.loc.getLongitude()).setScale(5, 
            BigDecimal.ROUND_HALF_UP).toPlainString(), 
          Toast.LENGTH_LONG).show(); 
       } catch (Exception e) { 
        e.printStackTrace(); 
        Toast.makeText(getApplicationContext(), 
          "GPS Problem!", 
          Toast.LENGTH_LONG).show(); 
       } 
       return false; 
      } 
     }); 

    } 

    // And the following method is courtesy of 'abi', a StackOverflow contributor from Dubai 
    public static String getFL(double latitude, double longitude) 
    { 
     try { 
      int latSeconds = (int) Math.round(latitude * 3600); 
      int latDegrees = latSeconds/3600; 
      latSeconds = Math.abs(latSeconds % 3600); 
      int latMinutes = latSeconds/60; 
      latSeconds %= 60; 

      int longSeconds = (int) Math.round(longitude * 3600); 
      int longDegrees = longSeconds/3600; 
      longSeconds = Math.abs(longSeconds % 3600); 
      int longMinutes = longSeconds/60; 
      longSeconds %= 60; 
      String latDegree = latDegrees >= 0 ? "N" : "S"; 
      String lonDegree = longDegrees >= 0 ? "E" : "W"; 

      return Math.abs(latDegrees) + "° " + latMinutes + "' " + latSeconds 
        + "\"" + latDegree + " " + Math.abs(longDegrees) + "° " + longMinutes 
        + "' " + longSeconds + "\"" + lonDegree; 
     } catch (Exception e) { 

      return "" + String.format("%8.5f", latitude) + "\n" 
        + String.format("%8.5f", longitude); 
     } 
    } 



    @Override 
    public void onLocationChanged(Location location) { 
     LatLng myLastPosition = new LatLng(location.getLatitude(), location.getLongitude()); 
     mMap.moveCamera(CameraUpdateFactory.newLatLng(myLastPosition)); 
     float zoomvalue = mMap.getCameraPosition().zoom; 
     mMap.animateCamera(CameraUpdateFactory.zoomTo(zoomvalue)); 
    } 

    @Override 
    public void onStatusChanged(String provider, int status, Bundle extras) { 

    } 

    @Override 
    public void onProviderEnabled(String provider) { 

    } 

    @Override 
    public void onProviderDisabled(String provider) { 

    } 
} 

google_maps_api.xml文件

<resources> 
<!-- 
TODO: Before you run your application, you need a Google Maps API key. 

To get one, follow this link, follow the directions and press "Create" at the end: 

https://console.developers.google.com/flows/enableapi?apiid=maps_android_backend&keyType=CLIENT_SIDE_ANDROID&r=6F:57:6E:22:FE:D8:BD:E9:C4:23:33:A9:1D:E5:C6:E9:6F:F8:5F:BD%3Bowner.example.com.locator 

You can also add your credentials to an existing key, using this line: 
6F:57:6E:22:FE:D8:BD:E9:C4:23:33:A9:1D:E5:C6:E9:6F:F8:5F:BD;owner.example.com.locator 

Once you have your key (it starts with "AIza"), replace the "google_maps_key" 
string in this file. 
--> 
<string name="google_maps_key" translatable="false" templateMergeStrategy="preserve"> 
    AIzaSyDRtOnaTU1Jc-zxuirnbyNojZn9uasd7eE 
</string> 
</resources> 

的build.gradle(模塊:應用程序)文件

apply plugin: 'com.android.application' 

android { 
signingConfigs { 
    config { 
     keyAlias 'myreleasekey' 
     keyPassword 'xxxxxxxx' 
     storeFile file('C:/Users/Owner/AndroidStudioProjects/release.jks') 
     storePassword 'xxxxxxxx' 
    } 
} 
compileSdkVersion 23 
buildToolsVersion "23.0.1" 
useLibrary 'org.apache.http.legacy' 
defaultConfig { 
    applicationId "owner.example.com.locator" 
    minSdkVersion 19 
    targetSdkVersion 23 
    versionCode 1 
    versionName "1.0" 
    signingConfig signingConfigs.config 
} 
buildTypes { 
    release { 
     minifyEnabled true 
     proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 
    } 
    debug { 
    } 
} 
productFlavors { 
} 
} 

dependencies { 
compile fileTree(include: ['*.jar'], dir: 'libs') 
compile 'com.android.support:appcompat-v7:23.0.1' 
compile 'com.google.android.gms:play-services:+' 
} 

回答

0

在我看來,你需要一個釋放鍵。對於Google Maps API v2,您需要使用SHA-1指紋。所以:

  • 使用密鑰工具創建應用的釋放證明
  • 獲得再次使用密鑰工具釋放證書SHA-1指紋;
  • 創建您的發佈API密鑰並將SHA-1添加到它。

所有這一切都可以發現here

+0

謝謝Iain,但build.gradle文件中的東西並不顯示我已經有一個API密鑰?我以爲我完全按照程序進行,但必須承認並不完全瞭解這一過程。你是否建議我重新開始? –

+1

John先前添加的API密鑰是由開發環境中使用的調試SHA-1生成的。正如@lain所說,爲了釋放目的,您需要釋放密鑰的SHA-1所產生的API密鑰。 – nitinkumarp

+0

你是否設法解決它約翰? – Iain

0

除了SHA鍵,您應該啓用地圖在Google account API訪問。點擊「Google Maps Android API」,然後點擊「啓用」。

相關問題