代码之家  ›  专栏  ›  技术社区  ›  sourdesi

GoogleMap变量上的Google Maps API空指针异常

  •  1
  • sourdesi  · 技术社区  · 12 年前

    我正在开发一个需要使用谷歌地图API的应用程序。我已经处理这个问题两天了。我使用API的版本2,所以我使用的是地图片段。所以,当我试图从地图片段中获取谷歌地图并将其分配给我的 GoogleMap googleMap 变量,它抛出一个空指针异常。我猜它很难找到存储GoogleMap对象的片段。我几乎试过了所有的方法。我尝试使用支持映射片段将片段放在我的主活动的xml文件中,并通过编程将片段添加到我的xml文件。这些解决方案还出现了其他问题,但NPE在所有解决方案中都是一致的。我觉得我现在已经很接近了,但我只需要一点帮助就可以让它最终发挥作用。

    这是我的谷歌地图活动代码:

    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"/> 在最底层。不过,这并不能阻止该应用程序的编译和安装。非常感谢您的帮助。

    2 回复  |  直到 12 年前
        1
  •  1
  •   MaciejGórski    12 年前

    很少有事情会搞砸:

    1. 使用FragmentActivity时使用getSupportFragmentManager
    2. 如果您想通过id查找片段,那么它必须存在于布局文件中
    3. 您想在布局或代码中添加片段( fragment = new com.parse.starter.MapFragment(); )-不是两者都有
    4. 什么是com.parse.starter.MapFragment?

    编辑 :Manifest中也有一些东西。。。

    可能还有更多的东西,但我建议从一个简单的项目开始,比如谷歌播放服务库中的地图样本。

    编辑2 :清单中的错误内容:

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

    您不能使用xml在片段中嵌套片段。只能使用代码实例化嵌套片段并使用 getChildFragmentManager .

    我仍然没有看到你的MapFragment代码,但如果你真的需要这个额外的片段,请考虑封装:如果谷歌的MapFraction在你的MapFragment中(最好更改名称),那么你的Map片断应该与嵌套片段进行任何交互,而不是与Activity进行交互。

        2
  •  -1
  •   MarmiK hirra    11 年前

    使用 getSupportFragmentManager 使用时 FragmentActivity

    如果你想通过id找到片段,那么它必须存在于你想在布局中添加片段的布局文件中 或在代码中 (fragment = new com.parse.starter.MapFragment();)

    注意:不得同时使用

    什么是com.parse.starter.MapFragment?