You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android集成Google Streetview API遇阻,XML片段识别异常求助

问题:Android集成Google Street View API实现随机点位街景展示及XML布局问题

我在谷歌上找不到合适的资源,GPT也没给出有效方案。现在我要在Android项目里集成Google Street View API,让随机生成的标记点显示对应街景,但不知道具体怎么实现。同时XML里的片段提示未知,我想让地图和街景同屏显示,试过FrameLayout但更倾向用Fragment实现。作为编程新手,我不确定Google Streetview API是否正确导入,恳请帮助。


现有Java代码

public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {

    private AppBarConfiguration appBarConfiguration;
    private ActivityMainBinding binding;
    private GoogleMap myMap;
    private Geocoder geocoder;
    private static final double MIN_LATITUDE = -90;
    private static final double MAX_LATITUDE = 90;
    private static final double MIN_LONGITUDE = -180;
    private static final double MAX_LONGITUDE = 180;

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

        String geocodingApiKey = getResources().getString(R.string.com_google_android_geo_API_KEY_value1);
        String mapsApiKey = getResources().getString(R.string.com_google_android_geo_API_KEY_value2);

        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
        setSupportActionBar(binding.toolbar);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onMapReady(@NonNull GoogleMap googleMap) {
        myMap = googleMap;

        Random random = new Random();
        double lat = MIN_LATITUDE + (MAX_LATITUDE - MIN_LATITUDE) * random.nextDouble();
        double lng = MIN_LONGITUDE + (MAX_LONGITUDE - MIN_LONGITUDE) * random.nextDouble();
        LatLng randomLocation = new LatLng(lat, lng);

        Geocoder geocoder = new Geocoder(this, Locale.getDefault());
        ArrayList<Address> addresses = null;
        try {
            addresses = (ArrayList<Address>) geocoder.getFromLocation(lat, lng, 1);
            if (addresses.size() > 0) {
                Address address = addresses.get(0);
                String locality = address.getLocality();
                String adminArea = address.getAdminArea();
                String countryName = address.getCountryName();
                String postalCode = address.getPostalCode();
                // use the address information as needed
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        }

        // street view

        //add marker w address as title
        String addressString = addresses.get(0).getAddressLine(0);
        myMap.addMarker(new MarkerOptions().position(randomLocation).title(addressString));
        myMap.moveCamera(CameraUpdateFactory.newLatLng(randomLocation));
    }

    public void showStreetView() {

    }
}

现有XML代码

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 
xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:app="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=".MainActivity">         

<androidx.fragment.app.FragmentContainerView 
android:layout_width="match_parent" 
android:layout_height="match_parent" android:id="@+id/map" 
tools:context=".MapsActivity" 
android:name="com.google.android.gms.maps.SupportMapFragment" /> 

<androidx.fragment.app.FragmentContainerView 
android:id="@+id/streetviewpanorama_fragment" 
android:name="com.google.android.gms.maps.SupportMapFragment" 
android:layout_width="match_parent" 
android:layout_height="match_parent" /> 

<com.google.android.gms.maps.StreetViewPanoramaView 
android:id="@+id/street_view_panorama" 
android:layout_width="match_parent" 
android:layout_height="match_parent" android:visibility="gone" /> 

<com.google.android.material.appbar.AppBarLayout 
android:layout_width="match_parent" 
android:layout_height="wrap_content" 
android:theme="@style/Theme.TheRealFinalGeoGuesser.AppBarOverlay">     

<androidx.appcompat.widget.Toolbar android:id="@+id/toolbar" 
android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" 
android:background="?attr/colorPrimary" 
app:popupTheme="@style/Theme.TheRealFinalGeoGuesser.PopupOverlay" /> 
</com.google.android.material.appbar.AppBarLayout>  

<include layout="@layout/content_main" /> 

</androidx.coordinatorlayout.widget.CoordinatorLayout>

解决方案

一、确认Google Street View API导入及配置

  • 在build.gradle(Module)中添加依赖:
    dependencies {
        implementation 'com.google.android.gms:play-services-maps:18.2.0'
        implementation 'com.google.android.gms:play-services-streetview:18.0.0'
    }
    
  • 在AndroidManifest.xml中添加权限和API密钥:
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    
    <application>
        <meta-data
            android:name="com.google.android.geo.API_KEY"
            android:value="你的Google Cloud API密钥"/>
    </application>
    
  • 登录Google Cloud控制台,启用Street View API和Maps SDK for Android,确保API密钥拥有这两项服务的调用权限。

二、修正XML布局(实现地图与街景同屏)

你的XML存在两处错误:街景Fragment的类名写错,且两个全屏Fragment会互相覆盖。改用LinearLayout分屏显示:

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="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=".MainActivity">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/Theme.TheRealFinalGeoGuesser.AppBarOverlay">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/Theme.TheRealFinalGeoGuesser.PopupOverlay" />
    </com.google.android.material.appbar.AppBarLayout>

    <!-- 左右分屏显示地图和街景 -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        android:layout_marginTop="?attr/actionBarSize">

        <!-- 地图Fragment -->
        <androidx.fragment.app.FragmentContainerView
            android:id="@+id/map"
            android:name="com.google.android.gms.maps.SupportMapFragment"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1" />

        <!-- 街景Fragment(修正类名) -->
        <androidx.fragment.app.FragmentContainerView
            android:id="@+id/streetviewpanorama_fragment"
            android:name="com.google.android.gms.maps.StreetViewPanoramaFragment"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1" />
    </LinearLayout>

    <include layout="@layout/content_main" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

三、实现随机点位的街景展示

  1. 在MainActivity中添加街景对象声明:
    private StreetViewPanorama mStreetViewPanorama;
    
  2. 在onCreate中初始化街景Fragment:
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // ... 原有代码 ...
    
        // 初始化街景Fragment
        StreetViewPanoramaFragment streetViewFragment =
                (StreetViewPanoramaFragment) getSupportFragmentManager()
                        .findFragmentById(R.id.streetviewpanorama_fragment);
        streetViewFragment.getStreetViewPanoramaAsync(new OnStreetViewPanoramaReadyCallback() {
            @Override
            public void onStreetViewPanoramaReady(StreetViewPanorama panorama) {
                mStreetViewPanorama = panorama;
            }
        });
    }
    
  3. 修改onMapReady方法,处理随机点位并加载街景(修复空指针问题):
    @Override
    public void onMapReady(@NonNull GoogleMap googleMap) {
        myMap = googleMap;
    
        Random random = new Random();
        double lat = MIN_LATITUDE + (MAX_LATITUDE - MIN_LATITUDE) * random.nextDouble();
        double lng = MIN_LONGITUDE + (MAX_LONGITUDE - MIN_LONGITUDE) * random.nextDouble();
        LatLng randomLocation = new LatLng(lat, lng);
    
        Geocoder geocoder = new Geocoder(this, Locale.getDefault());
        ArrayList<Address> addresses = null;
        String addressString = "未知地点";
        try {
            addresses = (ArrayList<Address>) geocoder.getFromLocation(lat, lng, 1);
            if (addresses != null && addresses.size() > 0) {
                Address address = addresses.get(0);
                addressString = address.getAddressLine(0) != null ? address.getAddressLine(0) : "未知地点";
                // 添加标记
                myMap.addMarker(new MarkerOptions().position(randomLocation).title(addressString));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        }
    
        // 移动地图到随机点位
        myMap.moveCamera(CameraUpdateFactory.newLatLngZoom(randomLocation, 12));
    
        // 加载街景
        if (mStreetViewPanorama != null) {
            mStreetViewPanorama.setPosition(randomLocation);
            // 监听街景加载状态
            mStreetViewPanorama.setOnStreetViewPanoramaChangeListener(location -> {
                if (location == null) {
                    Toast.makeText(MainActivity.this, "该地点无街景数据", Toast.LENGTH_SHORT).show();
                }
            });
        }
    }
    

四、额外注意事项

  • 随机生成的经纬度可能位于无街景区域,必须添加加载失败提示。
  • Android 6.0及以上版本,需要动态申请ACCESS_FINE_LOCATION权限,否则Geocoder可能无法正常工作。
  • 测试阶段暂时关闭API密钥的IP/应用限制,避免权限问题。

内容的提问来源于stack exchange,提问作者dudewhoislearning

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 14:38:10