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

Android地图Fragment无法聚焦当前位置,本地AVD异常求助

Android地图功能异常排查与修复

问题概述

我开发的Android应用包含Map Fragment,原本启动后会自动缩放聚焦到用户当前位置,运行正常。拉取同事开发的导航栏功能分支后,地图能正常显示,但无法设置想要的地标类型。删除原AVD并创建新AVD后,地图不再自动缩放聚焦当前位置,点击SET按钮设置地标类型时出现错误:

E/libprocessgroup: set_timerslack_ns write failed: Operation not permitted

该应用在同事的模拟器上运行正常,但我的环境中出现上述问题。

布局文件(activity_landin_page.xml)

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
    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"
    android:id="@+id/drawer_layout"
    tools:context=".LandinPage">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

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

        <fragment
            android:id="@+id/mapfragment"
            class="com.google.android.gms.maps.SupportMapFragment"
            android:layout_width="match_parent"
            android:layout_height="500dp"
            tools:layout_editor_absoluteX="-16dp" />

    </LinearLayout>

    <RelativeLayout
        android:layout_width="300dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="@color/white">

        <include
            layout="@layout/main_nav_drawer"/>
    </RelativeLayout>

    <Spinner
        android:id="@+id/spType"
        android:layout_width="409dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="550dp"
        android:layout_marginBottom="130dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent" />

    <Button
        android:id="@+id/btnSet"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="600dp"
        android:layout_marginBottom="80dp"
        android:text="SET"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/mapfragment" />

</androidx.drawerlayout.widget.DrawerLayout>

主页面代码(LandinPage.java)

package com.example.final_opsc_task2;

import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.FragmentActivity;

import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;

import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.List;

public class LandinPage extends FragmentActivity implements OnMapReadyCallback {

    Spinner spType;
    Button btnSet;
    GoogleMap map;
    FusedLocationProviderClient fusedLocationProviderClient;
    double currentLat = 0, currentLong = 0;
    SupportMapFragment supportMapFragment;

    DrawerLayout drawerLayout;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_landin_page);

        spType = findViewById(R.id.spType);
        btnSet = findViewById(R.id.btnSet);
        supportMapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.mapfragment);

        String[] PlaceName = {"bank", "diner", "hotel", "beach"};
        String[] TypeOfPlace = {"Bank", "Diner", "Hotel", "Beach"};

        spType.setAdapter(new ArrayAdapter<>(LandinPage.this,
                android.R.layout.simple_spinner_dropdown_item, TypeOfPlace));

        fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
        if (ActivityCompat.checkSelfPermission(LandinPage.this,
                Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            getCurrentLocation();
        } else {
            ActivityCompat.requestPermissions(LandinPage.this,
                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 44);
        }


        btnSet.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                int i = spType.getSelectedItemPosition();

                String url = "https://maps.googleapis.com/maps/api/place/nearbysearch/json" +
                        "?location=" + currentLat + "," + currentLong +
                        "&radius=5000" +
                        "&types=" + TypeOfPlace[i] +
                        "&sensor=true" +
                        "&key=" + getResources().getString(R.string.google_map_key);

                new PlaceTask().execute(url);
            }
        });

        drawerLayout = findViewById(R.id.drawer_layout);
    }

    public void ClickMenu(View view) {
        openDrawer(drawerLayout);
    }

    public static void openDrawer(DrawerLayout drawerLayout) {
        drawerLayout.openDrawer(GravityCompat.START);
    }

    public void ClickLogo(View view) {
        closeDrawer(drawerLayout);
    }

    public static void closeDrawer(DrawerLayout drawerLayout) {
        if(drawerLayout.isDrawerOpen(GravityCompat.START)) {
            drawerLayout.closeDrawer(GravityCompat.START);
        }
    }

    public void ClickHome(View view) {
        recreate();
    }

    public void ClickGoals(View view) {
        redirectActivity(this,Goals.class);
    }

    public void ClickFavourites(View view) {
        redirectActivity(this,FavouritePage.class);
    }

    public void ClickSettings(View view) {
        redirectActivity(this,AccountSettings.class);
    }

    public void ClickLogout(View view) {
        logout(this);
    }

    public static void logout(Activity activity) {
        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
        builder.setTitle("Log out");
        builder.setMessage("Are you sure you want to log out?");
        builder.setPositiveButton("YES", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                activity.finishAffinity();
                System.exit(0);
            }
        });
        builder.setNegativeButton("NO", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        });
        builder.show();
    }

    public static void redirectActivity(Activity activity, Class aClass) {
        Intent intent = new Intent(activity,aClass);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        activity.startActivity(intent);
    }

    @Override
    protected void onPause() {
        super.onPause();
        closeDrawer(drawerLayout);
    }

    private void getCurrentLocation() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        Task<Location> task = fusedLocationProviderClient.getLastLocation();
        task.addOnSuccessListener(new OnSuccessListener<Location>() {
            @Override
            public void onSuccess(Location location) {
                if(location != null) {
                    currentLat = location.getLatitude();
                    currentLong = location.getLongitude();

                    supportMapFragment.getMapAsync(new OnMapReadyCallback() {
                        @Override
                        public void onMapReady(@NonNull GoogleMap googleMap) {
                            map = googleMap;

                            map.animateCamera(CameraUpdateFactory.newLatLngZoom(
                                    new LatLng(currentLat,currentLong), 10
                            ));

                        }
                    });

                }
            }
        });
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == 44) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                getCurrentLocation();
            }
        }
    }

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

        map.animateCamera(CameraUpdateFactory.newLatLngZoom(
                new LatLng(currentLat,currentLong), 15
        ));
    }


    private class PlaceTask extends AsyncTask<String,Integer,String>{

        @Override
        protected String doInBackground(String... strings) {
            String data = null;
            try {
                data = downloadUrl(strings[0]);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return data;
        }

        @Override
        protected void onPostExecute(String s) {
            new ParserTask().execute(s);
        }
    }
    private String downloadUrl(String string) throws IOException {
        URL url = new URL(string);

        HttpURLConnection connection = (HttpURLConnection) url.openConnection();

        connection.connect();

        InputStream stream = connection.getInputStream();

        BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
        StringBuilder builder = new StringBuilder();
        String line = "";
        while ((line = reader.readLine()) != null){
            builder.append(line);
        }
        String data = builder.toString();
        reader.close();

        return data;
    }

    private class ParserTask  extends AsyncTask<String,Integer,List<HashMap<String,String>>> {
        @Override
        protected List<HashMap<String,String>> doInBackground(String... strings) {

            JsonParser jsonParser = new JsonParser();

            List<HashMap<String,String>> mapList = null;
            JSONObject object = null ;
            try {
                 object = new JSONObject(strings[0]);
                 mapList = jsonParser.parseResult(object);
            } catch (JSONException e) {
                e.printStackTrace();
            }
            return mapList;
        }

        @Override
        protected void onPostExecute(List<HashMap<String, String>> hashMaps) {
            for (int i=0; i<hashMaps.size();i++) {
                HashMap<String,String> hashMapList = hashMaps.get(i);

                double lat = Double.parseDouble(hashMapList.get("lat"));
                double lng = Double.parseDouble((hashMapList.get("lng")));
                String name = hashMapList.get("name");
                LatLng latLng = new LatLng(lat,lng);

                MarkerOptions options = new MarkerOptions();
                options.position(latLng);
                options.title(name);

                map.addMarker(options);

            }
        }
    }
}

问题修复方案

1. 地标类型设置失效问题

Google Places API的types参数要求使用小写的类型标识符(如"bank"),但当前代码使用了显示名称(如"Bank")。修改按钮点击事件中的URL拼接逻辑:

// 原代码
"&types=" + TypeOfPlace[i] +
// 修改为
"&types=" + PlaceName[i] +

PlaceName数组存储的是符合API要求的小写类型值,替换后即可正确请求对应类型的地标。

2. 地图不自动聚焦当前位置问题

  • 模拟器位置设置:新AVD默认无模拟位置,打开模拟器的"Extended controls"(三点图标)→ "Location",输入经纬度或选择预设位置,点击"Set location"。
  • 调整地图与位置初始化顺序:先初始化地图,再获取位置更新相机,避免因地图未初始化导致缩放失效:
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_landin_page);
    
        // ... 其他初始化代码 ...
    
        // 先初始化地图
        supportMapFragment.getMapAsync(this);
    
        // 再获取位置
        fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            getCurrentLocation();
        } else {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 44);
        }
    }
    
    // 修改getCurrentLocation中的地图更新逻辑
    private void getCurrentLocation() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        Task<Location> task = fusedLocationProviderClient.getLastLocation();
        task.addOnSuccessListener(new OnSuccessListener<Location>() {
            @Override
            public void onSuccess(Location location) {
                if(location != null && map != null) {
                    currentLat = location.getLatitude();
                    currentLong = location.getLongitude();
                    // 使用已初始化的map对象直接更新相机
                    map.animateCamera(CameraUpdateFactory.newLatLngZoom(
                            new LatLng(currentLat,currentLong), 15
                    ));
                }
            }
        });
    }
    
  • 处理LastLocation为空的情况:新模拟器可能无位置历史,getLastLocation会返回null,需添加实时位置请求逻辑:
    // 添加依赖(build.gradle)
    implementation 'com.google.android.gms:play-services-location:21.0.1'
    
    // 在LandinPage中添加LocationCallback
    private LocationCallback locationCallback = new LocationCallback() {
        @Override
        public void onLocationResult(@NonNull LocationResult locationResult) {
            super.onLocationResult(locationResult);
            if (locationResult.getLastLocation() != null && map != null) {
                Location location = locationResult.getLastLocation();
                currentLat = location.getLatitude();
                currentLong = location.getLongitude();
                map.animateCamera(CameraUpdateFactory.newLatLngZoom(
                        new LatLng(currentLat, currentLong), 15
                ));
                // 获取到位置后停止请求
                fusedLocationProviderClient.removeLocationUpdates(this);
            }
        }
    };
    
    // 修改getCurrentLocation方法
    private void getCurrentLocation() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        Task<Location> task = fusedLocationProviderClient.getLastLocation();
        task.addOnSuccessListener(new OnSuccessListener<Location>() {
            @Override
            public void onSuccess(Location location) {
                if(location != null && map != null) {
                    currentLat = location.getLatitude();
                    currentLong = location.getLongitude();
                    map.animateCamera(CameraUpdateFactory.newLatLngZoom(
                            new LatLng(currentLat,currentLong), 15
                    ));
                } else {
                    // LastLocation为空,请求实时位置
                    LocationRequest locationRequest = LocationRequest.create();
                    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
                    locationRequest.setInterval(1000);
                    fusedLocationProviderClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper());
                }
            }
        });
    }
    

3. "set_timerslack_ns write failed"错误

该错误是Android 11+模拟器的系统级警告,通常不影响应用功能,可通过以下方式缓解:

  • 将模拟器系统版本降级到Android
相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 23:45:39