膨胀类片段时出错。无法在谷歌播放服务中获得FragmentManager

时间:2016-07-06 08:45:19

标签: android maven google-play-services robolectric

这是我的Maven项目,我尝试测试google-map活动。

...
    <dependency>
        <groupId>com.almende.eve</groupId>
        <artifactId>eve-bundle-android-ws</artifactId>
        <version>3.1.1</version>
    </dependency>
...

我使用3种版本

<dependency>
     <groupId>com.google.android.gms</groupId>
     <artifactId>play-services</artifactId>
     <version>x.y.z</version>
     <scope>compile</scope>     
     <type>aar</type>
</dependency>

如果x.y.z是8.3.0,那么

android.view.InflateException: XML file ./src/main/res/layout/main.xml line #-1 (sorry, not yet implemented): Error inflating class fragment
        at com.eduonix.app.EduonixActivityTest.setup(EduonixActivityTest.java:38)
Caused by: android.content.res.Resources$NotFoundException: String resource ID #0x7f070028
        at com.eduonix.app.EduonixActivityTest.setup(EduonixActivityTest.java:38)

那个ID对应R级的common_google_play_services_install_text_phone constats。

如果x.y.z是7.0.0那么

java.lang.NoSuchFieldError: MapAttrs_ambientEnabled
at com.eduonix.app.EduonixActivityTest.setup(EduonixActivityTest.java:38)

Android sdk为22,因此8.3.0更正确,但同样的错误也显示为9.2.0。

我的活动是

    public class EduonixActivity extends android.support.v4.app.FragmentActivity  {

        protected com.google.android.gms.maps.GoogleMap map;

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main); System.out.println("hello!");
            android.support.v4.app.FragmentManager fM =  getSupportFragmentManager(); // error line
            System.out.println("FragmentManager is initiated"); // this line is not achieved
            SupportMapFragment fm = (SupportMapFragment)fM.findFragmentById(R.id.map);
            System.out.println("fm is initiated");
            map = fm.getMap();
            System.out.println("map is initiated");
        }
    }

尝试测试Robolectic框架

时,Maven构建过程中断了
    @Config(manifest = "src/main/AndroidManifest.xml")
    @RunWith(RobolectricTestRunner.class)
    public class EduonixActivityTest {

        private EduonixActivity activity;

        @Before
        public void setup() { 
            activity = Robolectric.buildActivity(EduonixActivity.class).create().start().get();// error
        }

        @Test
        public void testEduonixActivity() {
            assertThat(activity).isNotNull();
        }
    }

AndroidManifest.xml是

    <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          android:versionCode="2"
          android:versionName="1.0.0-SNAPSHOT"
          package="com.eduonix.app">

    <uses-sdk android:minSdkVersion="22"
              android:targetSdkVersion="22"/>

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
    <!-- External storage for caching. -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <!-- My Location -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
        <!-- Maps API needs OpenGL ES 2.0. -->
    <uses-feature
            android:glEsVersion="0x00020000"
            android:required="true"/>
    <application android:name="com.eduonix.app.EduonixApplication">

        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />
    <meta-data
            android:name="com.google.android.geo.API_KEY"
            android:value="@string/google_maps_key" />
        <activity android:name=".EduonixActivity" android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>


    </application>
</manifest>

任何想法都将受到赞赏。

1 个答案:

答案 0 :(得分:0)

在比较android.app.Fragment和andoriod.app.support.v4Fragment之后,答案是:Robolectic无法膨胀片段,因为Google服务不可用。所以解决方案就是像这样指定Fragment inflater

public class MyFragment extends  com.google.android.gms.maps.SupportMapFragment{
static private MyFragment fragment = new MyFragment();
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_stub_for_test, container);
    return view;
    }
// public constructor must be empty
static public MyFragment getInstance(){
    return fragment;
    }
}

其中test-stub可以是布局中的一些xml:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/LinearLayout2"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    tools:context="com.example.zheka.gmapexample1.MapsActivity" >

    <TextView
        android:id="@+id/tvDisplayText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="No Passed Bundle :(" />
    </LinearLayout>

当然,对于Android部署,必须在SupportMapFragment上替换此指定的Fragment:

  <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/LinearLayout1"    
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    tools:context="com.example.zheka.gmapexample1.MapsActivity" >

<fragment 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:id="@+id/map"
    android:name="com.google.android.gms.maps.SupportMapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />    
</LinearLayout>

其中android:name=pkgName.MyFragment为测试模式。为了测试和部署我在@RunWith中指定的MyTestRunner类,以便定义测试资源文件夹,如src / test / res

  @Config(manifest = "src/main/AndroidManifest.xml"
    ,shadows = {
        //ShadowActivity.class
        //,ShadowGooglePlayServicesUtil.class
        //ShadowMapsActivity.class
        }
)
@RunWith(RobolectricTestRunner.class)
//@RunWith(MyTestRunner.class)
public class ExampleUnitTest {
    MapsActivity activity;
    android.support.v4.app.Fragment fragment;

    @Before
    public void setup(){
        activity = Robolectric.buildActivity(MapsActivity.class)
                .create()
                .start() //no activity error can happen, if so just commment 
                .get();
    }
    @Test
    public void testActivity() {
        assertThat(activity).isNotNull();
    }
    @Test
    public void testMap() {
        fragment = (SupportMapFragment)activity.getSupportFragmentManager().findFragmentById(R.id.map);
        assertThat(fragment).isNotNull();
        ((SupportMapFragment)fragment).getMapAsync(new OnMapReadyCallback(){

            @Override
            public void onMapReady(GoogleMap map) {
                org.junit.Assert.assertTrue(map!=null);             
            }
        });
    }
    }

对于8.1.0以上版本的播放服务和播放服务地图,所有测试现在都很好。