如何接收 GPS 位置并膨胀 Fragment MapView 以使用 SyncAdapter 以编程方式添加标记

How to receive GPS Location and inflate Fragment MapView to programmatically add markers with SyncAdapter

好吧,在阅读了本网站的许多示例和帖子后,我解决了一些问题,最后我设法让片段响应并且我的 syncAdapter 工作。但是经过这么多天尝试了很多东西我还是看不到地图。我只有一个空白屏幕。我已经尝试了一些东西,但它对我不起作用。 我遇到了这个问题,我需要继续推进我的项目。
有人可以指导我如何完成这项工作。我真的很感激。 我只是请你注意我拥有的所有元素,因为我一直在兜圈子,当我试图改变一些东西时,其他工作正常的东西就中断了。

此应用具有,如下所示:一个 Location 请求(主要 Activity)在 Change 和 returns GPS 上同步纬度和经度。之后它带来了 Fragment 然后我首先 Sync 使用 GPS lat 和 lon 发送这些数据以存储在数据库中 [= =43=]原理图。 syncAdapter 使用 GPS lat 和 lon 传递给 Yelp,据我所知,它执行异步调用。

仅供参考,我用过这样的帖子 one 但它对我不起作用。

我在导入 android.support.v4.app.xxxx 或简单导入 android.app.xxx 时很小心 因为它弄乱了其他东西。路是 运行 现在没有任何问题,但我还看不到地图。

我试过的:
(结果如重复的 id、Nullpointer) 很少有帖子说使用 getChildFragmentManager,使用 onDestroyView,使用 class SupportMapFragment,但没有任何效果。
这里是那些帖子:one, , three, four

阅读这些帖子后,我调整了如下代码并出现错误 "NullPointerException in the SupportMapFragment"。我也试过普通的 MapFragment 但什么也没有。


我将无法为此感谢你。
干杯


调整如下:(这部分必须将 minSdkVersion 更改为 17)


片段

 @Override
    public void onDestroyView()
    {
        super.onDestroyView();
        Fragment fragment = (getActivity().getSupportFragmentManager().findFragmentById(R.id.thismap));
        FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
        ft.remove(fragment);
        ft.commit();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        //getLoaderManager().initLoader(CURSOR_LOADER_ID, null, this);


                SupportMapFragment mapFragment = (SupportMapFragment) this.getChildFragmentManager()
                .findFragmentById(R.id.thismap);
        mapFragment.getMapAsync(this);
return null;
}

为 yelp_google_map.xml 试过这个(只有片段,没有别的)

<fragment android:id="@+id/thismap"
          android:name="com.google.android.gms.maps.SupportMapFragment"
          xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:map="http://schemas.android.com/apk/res-auto"
          xmlns:tools="http://schemas.android.com/tools"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          tools:context="mem.edu.joshua.MapsActivity"/>




没有上述调整的整个应用程序
Gradle

apply plugin: 'com.android.application'
apply plugin: 'android-apt'
//apply plugin: 'com.google.gms.google-services'

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.0"

    defaultConfig {
        applicationId "mem.edu.joshua"
        minSdkVersion 16
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
        multiDexEnabled true
    }

    dexOptions {
        preDexLibraries = false
        javaMaxHeapSize "4g"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    buildTypes.each {
        it.buildConfigField 'String', 'YELP_CONSUMER_KEY', YelpConsumerKey
        it.buildConfigField 'String', 'YELP_CONSUMER_SECRET', YelpConsumerSecret
        it.buildConfigField 'String', 'YELP_TOKEN', YelpToken
        it.buildConfigField 'String', 'YELP_TOKEN_SECRET', YelpTokenSecret
    }

}

repositories {
    mavenCentral()
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    apt 'net.simonvt.schematic:schematic-compiler:0.6.3'

    compile 'net.simonvt.schematic:schematic:0.6.3'
    compile 'com.android.support:appcompat-v7:24.1.1'
    compile 'com.google.firebase:firebase-ads:9.0.2'
    //compile 'com.google.android.gms:play-services-maps:9.2.1'
    compile 'com.google.android.gms:play-services-maps:9.0.2'
    compile 'com.google.android.gms:play-services-location:9.0.2'
    compile 'com.yelp.clientlib:yelp-android:2.0.0'
    compile 'org.scribe:scribe:1.3.7'
    //compile 'com.google.android.gms:play-services:9.2.1'
}

清单

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

    <!--
         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_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/>
    <uses-permission android:name="android.permission.READ_SYNC_SETTINGS"/>
    <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/Theme.AppCompat">
        <uses-library android:name="com.google.android.maps"/>

        <!--
             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=".MainActivity"
            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=".MapsActivity"-->
            <!--android:label="@string/app_name">-->
            <!--<meta-data-->
                <!--android:name="android.support.PARENT_ACTIVITY"-->
                <!--android:value="mem.edu.joshua.MainActivity"/>-->

            <!--<intent-filter>-->
                <!--<action android:name="android.intent.action.MAIN"/>-->

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

        <!-- android:accountType="com.clashtoolkit.clashtoolkit" -->
        <service android:name=".sync.AuthenticatorService">
            <intent-filter>
                <action android:name="android.accounts.AccountAuthenticator"/>
            </intent-filter>

            <meta-data
                android:name="android.accounts.AccountAuthenticator"
                android:resource="@xml/authenticator"/>
        </service>

        <!-- The SyncAdapter service -->
        <!-- android:allowParallelSyncs="true" -->
        <service
            android:name=".sync.SyncService"
            android:exported="true">
            <intent-filter>
                <action android:name="android.content.SyncAdapter"/>
            </intent-filter>

            <meta-data
                android:name="android.content.SyncAdapter"
                android:resource="@xml/syncadapter"/>
        </service>

        <provider
            android:name=".data.generated.QuoteProvider"
            android:authorities="mem.edu.joshua.data.QuoteProvider"
            android:exported="false"/>

    </application>

</manifest>

在mainActivity.java

@Override
    public void onConnected(@Nullable Bundle bundle) {

LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);

        mLocationRequest = LocationRequest.create();
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationRequest.setInterval(60000);


        try {

            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,mLocationRequest, (LocationListener) this);

            if (mLocationRequest != null) {
                Log.e(LOG_TAG, "google working");



//                FragmentManager manager = getSupportFragmentManager();
//                FragmentTransaction transaction = manager.beginTransaction();
//                SupportMapFragment fragment = new SupportMapFragment();
//                transaction.add(R.id.mapView, fragment);
//                transaction.commit();

                LocationManager service = (LocationManager) getSystemService(LOCATION_SERVICE);
                Criteria criteria = new Criteria();
                String provider = service.getBestProvider(criteria, false);
                Location location = service.getLastKnownLocation(provider);


                coord.setLon(location.getLongitude());
                coord.setLat(location.getLatitude());

                sPref.saveCoordBody("lat", coord.getLat());
                sPref.saveCoordBody("lon", coord.getLon());

                    getSupportFragmentManager()
                            .beginTransaction()
                            .add(R.id.container, new MapsActivity(), MapsActivity.LOG_TAG)
                            .disallowAddToBackStack()
                            .commit();


            }

        }catch  (SecurityException e) {
            Log.e(LOG_TAG, e.getMessage(), e);
            e.printStackTrace();
        }


    }

在 MapsActivity.java(片段 -> 导入 android.support。v4.app.FragmentActivity;)

public class MapsActivity extends Fragment implements OnMapReadyCallback, LoaderManager.LoaderCallbacks<Cursor> {

GoogleApiClient.ConnectionCallbacks,
        public static final String LOG_TAG = MapsActivity.class.getSimpleName();

    private static final int CURSOR_LOADER_ID = 0;

    private Context mContext;


    private MapCursor mMapCursor;
    protected Location mLastLocation;
    private Cursor initQueryCursor;
    private GetSet coord;
    private AppPreferences sPref;
    private LatLng home;
    private GoogleMap mMap;
    MapView mMapView;

    private GoogleMap googleMap;

        private static final String FRAGMENT_LISTS =
                "net.simonvt.schematic.samples.ui.SampleActivity.LISTS";




    public MapsActivity() {
    }


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);


        sPref = new AppPreferences(getActivity());

        SyncAdapter.syncImmediately(getActivity(),
                sPref.getCoordBody("lat"),
                sPref.getCoordBody("lon"));

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        //getLoaderManager().initLoader(CURSOR_LOADER_ID, null, this);


        View v = inflater.inflate(R.layout.yelp_google_map, container,
                false);


        mMapView = (MapView) v.findViewById(R.id.mapView);

        mMapView.onCreate(savedInstanceState);

        mMapView.onResume();

        mMapView.getMapAsync(this);

        return v;

    }


    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        return new CursorLoader(getActivity(), QuoteProvider.Quotes.CONTENT_URI,
                new String[]{ QuoteColumns._ID, QuoteColumns.DISPLAY_ADDRESS, QuoteColumns.DISPLAY_PHONE,
                        QuoteColumns.RATING, QuoteColumns.URL, QuoteColumns.POSTAL_CODE, QuoteColumns.ID_BUSINESS_NAME,
                        QuoteColumns.LATITUDE,
                        QuoteColumns.LOGITUDE},
                null,
                null,
                null);
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {

        if (loader != null) {
            //     mMapCursor.swapCursor(data);
            initQueryCursor = data;
        }
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {

    }


    @Override
    public void onResume() {
        super.onResume();
        mMapView.onResume();
    }


    @Override
    public void onMapReady(GoogleMap googleMap) {
        LatLngBounds.Builder builder = new LatLngBounds.Builder();

        mMap = googleMap;

        initQueryCursor = getContext().getContentResolver().query(QuoteProvider.Quotes.CONTENT_URI,
                new String[]{QuoteColumns.LATITUDE, QuoteColumns.LOGITUDE, QuoteColumns.ID_BUSINESS_NAME}, null,
                null, null);


        if (initQueryCursor != null) {

            DatabaseUtils.dumpCursor(initQueryCursor);
            initQueryCursor.moveToFirst();
            for (int i = 0; i < initQueryCursor.getCount(); i++) {

                home = new LatLng(Double.valueOf(initQueryCursor.getString(initQueryCursor.getColumnIndex("latitude"))),
                        Double.valueOf(initQueryCursor.getString(initQueryCursor.getColumnIndex("longitude"))));
                mMap.addMarker(new MarkerOptions().position(home).
                        title(initQueryCursor.getString(initQueryCursor.getColumnIndex("id_bussines_name"))));

                initQueryCursor.moveToNext();

                builder.include(home);
            }
            if(home!=null) {
                mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), 91, 91, 42));
            }
        }
    }
}

我的yelp_google_map.xml

<LinearLayout 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">

    <!--<include-->
        <!--android:id="@+id/map_toolbar"-->
        <!--layout="@layout/app_bar" />-->



    <LinearLayout

        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">


        <com.google.android.gms.maps.MapView
            android:id="@+id/mapView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            class="com.google.android.gms.maps.MapFragment" />
        <!--was SupportMapFragment-->
    </LinearLayout>
</LinearLayout>

经过拼命尝试,我找到了 Mrigank 在类似帖子中给出的解决方案 here 我相信在我对代码进行调整后,即使它被膨胀了,父容器在某种程度上还是空的。

所以我的 yelp_google_map.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"
                tools:context="mem.edu.joshua.MapsActivity"
                android:background="#009688">


    <fragment
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        class="com.google.android.gms.maps.SupportMapFragment" />

</RelativeLayout>

我去掉了@Override public void onDestroyView 部分

onCreateView 保持这样

顶级变量:
私有 SupportMapFragment sMap;
私人 FragmentManager fm;
私有 GoogleMap mMap;

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        getLoaderManager().initLoader(CURSOR_LOADER_ID, null, this);
        View v = inflater.inflate(R.layout.yelp_google_map, container, false);

        fm=getChildFragmentManager();

        sMap = ((SupportMapFragment) fm.findFragmentById(R.id.map));

        mMap = sMap.getMap();


        initQueryCursor = getActivity().getContentResolver().query(QuoteProvider.Quotes.CONTENT_URI,
                new String[]{QuoteColumns.LATITUDE, QuoteColumns.LOGITUDE, QuoteColumns.ID_BUSINESS_NAME}, null,
                null, null);

        LatLngBounds.Builder builder = new LatLngBounds.Builder();
        if (initQueryCursor != null) {

            DatabaseUtils.dumpCursor(initQueryCursor);
            initQueryCursor.moveToFirst();
            for (int i = 0; i < initQueryCursor.getCount(); i++) {

                home = new LatLng(Double.valueOf(initQueryCursor.getString(initQueryCursor.getColumnIndex("latitude"))),
                        Double.valueOf(initQueryCursor.getString(initQueryCursor.getColumnIndex("longitude"))));
                mMap.addMarker(new MarkerOptions().position(home).
                        title(initQueryCursor.getString(initQueryCursor.getColumnIndex("id_bussines_name"))));

                initQueryCursor.moveToNext();

                builder.include(home);
            }
            if(home!=null) {
                mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), 91, 91, 42));
            }
        }

        return v;

    }

将所有这些添加到同一个片段 java 文件中

 @Override
        public void onResume() {
            super.onResume();
            sMap.onResume();
        }

        @Override
        public void onPause() {
            super.onPause();
            sMap.onPause();
        }

        @Override
        public void onDestroy() {
            super.onDestroy();
            sMap.onDestroy();
        }

        @Override
        public void onLowMemory() {
            super.onLowMemory();
            sMap.onLowMemory();
        }

最后在 mainActivity.java

            getSupportFragmentManager()
                    .beginTransaction()
                    .add(R.id.map, new MapsActivity(), MapsActivity.LOG_TAG)
                    .disallowAddToBackStack()
                    .commitAllowingStateLoss();

希望这对某人有所帮助。这对我来说是一场噩梦。我的应用程序现在运行良好。