1

我正在研究需要使用Google Maps API的應用程序。我現在已經處理了這個問題兩天了。我使用API​​的版本2,所以我使用地圖片段。因此,當我嘗試從地圖片段中獲取Google地圖並將其分配給我的GoogleMap googleMap變量時,它會引發空指針異常。我猜它找不到存放GoogleMap對象的片段。我幾乎試過了所有的東西。我試圖用我的主要活動的XML文件,使用支持地圖片段,並以編程方式將片段添加到我的XML文件。這些解決方案出現了其他問題,但NPE在所有這些解決方案中都是一致的。我覺得我現在非常接近,但我需要一點幫助才能最終實現它。Google Maps API GoogleMap變量中的空指針異常

這是我的GoogleMaps活動代碼:

package com.parse.starter; 

import android.app.*; 
import android.content.Context; 
import android.content.DialogInterface; 
import android.content.Intent; 
import android.location.Criteria; 
import android.location.Location; 
import android.location.LocationListener; 
import android.location.LocationManager; 
import android.os.Bundle; 
import android.provider.Settings; 
import android.support.v4.app.FragmentActivity; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.Toast; 
import com.google.android.gms.common.ConnectionResult; 
import com.google.android.gms.common.GooglePlayServicesUtil; 
import com.google.android.gms.maps.*; 
import com.google.android.gms.maps.MapFragment; 
import com.google.android.gms.maps.model.*; 
import com.google.android.gms.maps.SupportMapFragment; 
import com.parse.*; 
import com.parse.starter.R; 

import java.util.List; 

public class OutbreakMap extends FragmentActivity implements LocationListener { 
    double lat=50; 
    double longi=50; 
    private LocationManager locationManager; 
    private String provider; 
    private GoogleMap googleMap; 
    Fragment fragment; 


    /** Called when the activity is first created. */ 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     if(isGooglePlayOn()) { 
      setContentView(R.layout.map_layout); 
     } 
     //Add the map fragment 
     FragmentManager fragmentManager = getFragmentManager(); 
     FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); 
     fragment = new com.parse.starter.MapFragment(); 
     fragmentTransaction.add(R.id.myfragment, fragment); 
     fragmentTransaction.commit(); 

     // Get the location manager 
     locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); 
     LocationManager service = (LocationManager) getSystemService(LOCATION_SERVICE); 
     boolean enabled = service.isProviderEnabled(LocationManager.GPS_PROVIDER); 

     // Check if enabled and if not send user to the GSP settings 
     // Better solution would be to display a dialog and suggesting to 
     // go to the settings 
     if (!enabled) { 
      AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this); 

      // set title 
      alertDialogBuilder.setTitle("Turn On Your GPS"); 

      // set dialog message 
      alertDialogBuilder 
        .setMessage("Please turn on your GPS to track sickness in your area!") 
        .setCancelable(false) 
        .setPositiveButton("Yes",new DialogInterface.OnClickListener() { 
         public void onClick(DialogInterface dialog,int id) { 
          // if this button is clicked, close 
          // current activity 
          OutbreakMap.this.finish(); 
          Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); 
          startActivity(intent); 
         } 
        }) 
        .setNegativeButton("No",new DialogInterface.OnClickListener() { 
         public void onClick(DialogInterface dialog,int id) { 
          // if this button is clicked, just close 
          // the dialog box and do nothing 
          dialog.cancel(); 
         } 
        }); 

      // create alert dialog 
      AlertDialog alertDialog = alertDialogBuilder.create(); 

      // show it 
      alertDialog.show(); 

     } 
     // Define the criteria how to select the locatioin provider -> use 
     // default 
     Criteria criteria = new Criteria(); 
     provider = locationManager.getBestProvider(criteria, false); 
     Location location = locationManager.getLastKnownLocation(provider); 

     // Initialize the location fields 
     if (location != null) { 
      System.out.println("Provider " + provider + " has been selected."); 
      onLocationChanged(location); 
     } else { 
      Toast.makeText(getApplicationContext(),"Location not found",Toast.LENGTH_SHORT).show(); 
     } 

     setUpMapIfNeeded(); 
     googleMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE); 
     if(location != null) { 
      lat=location.getLatitude(); 
      longi=location.getLongitude(); 
     } 

     CameraPosition cameraPosition = new CameraPosition.Builder() 
        .target(new LatLng(lat,longi))  // Sets the center of the map to lat,longi (which is 50,50 if the current location isnt found) 
        .zoom(17)     // Sets the zoom 
        .build();     // Creates a CameraPosition from the builder 
     googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition)); 

     UiSettings uiSettings=googleMap.getUiSettings(); 
     uiSettings.setAllGesturesEnabled(false); 
     // Initialize the location fields 
     if (location != null) { 
      System.out.println("Provider " + provider + " has been selected."); 
      onLocationChanged(location); 
     } else { 
     Toast.makeText(getApplicationContext(),"Couldn't Find Location",Toast.LENGTH_SHORT).show(); 
     } 



     ParseGeoPoint userLoc= new ParseGeoPoint(lat,longi); 
     ParseQuery query= new ParseQuery("Outbreak"); 
     query.whereWithinMiles("location",userLoc,1); 
     query.findInBackground(new FindCallback() { 
      public void done(List<ParseObject> objects, ParseException e) { 
       if (e == null) { 
       GetOutbreaks.getOutBreaksNearMe(googleMap,lat,longi,objects); 
       Toast.makeText(getApplicationContext(),"Recieved Outbreak Data",Toast.LENGTH_SHORT).show(); 
       } else { 
        e.printStackTrace(); 
        Toast.makeText(getApplicationContext(),"Could Not Download Data",Toast.LENGTH_SHORT).show(); 
       } 
      } 

     }); 


//  moveToPrescription(); 
//  moveToPrescription(); 
    } 


    /* Request updates at startup */ 
    @Override 
    protected void onResume() { 
     super.onResume(); 
     locationManager.requestLocationUpdates(provider, 400, 1, this); 
    } 

    /* Remove the locationlistener updates when Activity is paused */ 
    @Override 
    protected void onPause() { 
     super.onPause(); 
     locationManager.removeUpdates(this); 
    } 

    @Override 
    public void onLocationChanged(Location location) { 
     int lat = (int) (location.getLatitude()); 
     int lng = (int) (location.getLongitude()); 
    } 

    @Override 
    public void onStatusChanged(String provider, int status, Bundle extras) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void onProviderEnabled(String provider) { 
     Toast.makeText(this, "Enabled new provider " + provider, 
       Toast.LENGTH_SHORT).show(); 

    } 

    @Override 
    public void onProviderDisabled(String provider) { 
     Toast.makeText(this, "Disabled provider " + provider, 
       Toast.LENGTH_SHORT).show(); 
    } 

    public void moveToPrescription(){ 
     Intent intent = new Intent(this,Prescription.class); 
     startActivity(intent); 
    } 

    public void setUpMapIfNeeded() { 
     if(googleMap==null) { 
      googleMap= ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap(); 

     } 
     else { 

     } 
    } 

    public boolean isGooglePlayOn() { 
     int status=GooglePlayServicesUtil.isGooglePlayServicesAvailable(this); 
     if(status== ConnectionResult.SUCCESS) { 
      return true; 
     } 
     ((Dialog) GooglePlayServicesUtil.getErrorDialog(status,this,10)).show(); 
     Toast.makeText(this,"Google Play Services cannot be found", Toast.LENGTH_SHORT).show(); 
     return false; 
    } 

} 

這裏是我的活動我的XML文件(內線性佈局是用於在地圖片段保持器):

<?xml version="1.0" encoding="utf-8"?> 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
       android:orientation="vertical" 
       android:layout_width="match_parent" 
       android:layout_height="match_parent"> 

    <FrameLayout 
      android:id="@+id/mapContainer" 
      android:layout_width="fill_parent" 
      android:layout_height="fill_parent"> 
     <LinearLayout 
       android:id="@+id/myfragment" 
       android:layout_width="match_parent" 
       android:layout_weight="4" 
       android:layout_height="match_parent" /> 
    </FrameLayout> 
</LinearLayout> 

這裏是在地圖片段xml文件:

<?xml version="1.0" encoding="utf-8"?> 

<fragment xmlns:android="http://schemas.android.com/apk/res/android" 
      android:tag="map_fragment" 
      android:id="@+id/map" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      class="com.google.android.gms.maps.MapFragment"/> 

最後,這裏是我的Android清單:

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.parse.starter" 
    android:versionCode="1" 
    android:versionName="1.0" > 

    <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="15"/> 
    <permission 
      android:name="com.parse.starter.permission.MAPS_RECEIVE" 
      android:protectionLevel="signature"/> 
    <uses-permission android:name="com.parse.starter.permission.MAPS_RECEIVE"/> 
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> 
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 
    <uses-permission android:name="android.permission.INTERNET" /> 
    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/> 
    <!-- The following two 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"/> 
    <uses-permission android:name="android.permission.WAKE_LOCK"/> 

    <application 
     android:name="ParseApplication" 
     android:icon="@drawable/ic_launcher" 
     android:label="@string/app_name" > 
     <activity 
      android:name=".ParseStarterProjectActivity" 

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

       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 
     <activity android:name=".Register"/> 
     <activity android:name=".Login"/> 
     <activity android:name=".Home"/> 
     <activity android:name=".OutbreakMap"/> 
     <activity android:name=".Prescription"/> 
     <activity android:name=".MyPrescriptions"/> 
     <receiver android:name=".AlarmManagerBroadcastReceiver"></receiver> 

     <uses-library android:name="com.google.android.maps"/> 
     <meta-data 
       android:name="com.google.android.maps.v2.API_KEY" 
       android:value="MY API KEY IS HERE"/> 
    </application> 
    <uses-feature android:glEsVersion="0x00020000" android:required="true"/> 

</manifest> 

對不起,我沒有我的logcat的對話,因爲它得到了刪除,我測試的手機屬於一個朋友誰不得不離開。但它基本上說,有一個NPE在說setUpMapIfNeeded();googleMap= ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();。此外,值得注意的是,在AndroidManifest.xml文件中,它說「無法解析符號'0x00020000'」,它在最底部表示<uses-feature android:glEsVersion="0x00020000" android:required="true"/>。儘管如此,這並不能阻止應用程序的編譯和安裝。感謝所有的幫助,非常感謝。

回答

1

幾件事情搞砸了:有FragmentActivity

  • 工作

    1. 使用getSupportFragmentManager時,如果你想找到ID片段,那麼它必須在佈局文件中存在
    2. 要添加片段佈局或代碼(fragment = new com.parse.starter.MapFragment();) - 不是
    3. 什麼是com.parse.starter.MapFragment呢?

    編輯:和有東西在清單太...

    有可能是更多的東西,但我建議,從一個簡單的項目開始像在谷歌地圖樣本發揮服務庫。

    編輯2:在清單錯誤的東西:

    1. <uses-library android:name="com.google.android.maps"/>是不必要的
    2. <uses-sdk android:minSdkVersion="4"應該是8 - 可能是Cannot resolve symbol '0x00020000'

    內片段不能嵌套片段的原因用xml。您只能用代碼實例化嵌套片段並使用getChildFragmentManager

    我還是沒有看到你的MapFragment代碼,但是如果你真的需要這個額外的片段,想一想封裝:如果Google的MapFragment在你的MapFragment中(可以改變名字),那麼你的MapFragment應該做的任何與嵌套片段的交互,而不是活動。

  • +0

    感謝您的幫助!和'com.parse.starter.MapFragment();'是另一個類的愚蠢的名字選擇,它給出了地圖片段的膨脹視圖(我也把上面的代碼放在了上面)。另外,我相信我目前只是以編程方式放入片段。我從'com.parse.starter.MapFragment();'並將其放置在我活動的佈局xml文件的內部線性佈局中。如果我對此有錯,請糾正我。另外,我的Android Manifest中出了什麼問題? – sourdesi 2013-04-08 01:24:00

    -1

    使用getSupportFragmentManagerFragmentActivity

    工作時,如果你想找到ID片段,那麼它必須在佈局文件中存在要在佈局 或代碼 (fragment = new com.parse.starter.MapFragment();)

    注意添加片段:必須不要同時使用

    什麼是com.parse.starter.MapFragment呢?