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

Android Studio点击按钮播报位置却循环重复的问题求助

问题描述

我有一个按钮,点击后会在两个TextView(textview3显示纬度X,textview21显示经度Y)中显示当前位置,同时希望通过TextToSpeech播报该位置。但现在遇到的问题是文本转语音会一直循环播报位置,只有关闭程序才能停止,不知道怎么修复。


MainActivity2 定位处理代码

ImageButtonLoc.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (ActivityCompat.checkSelfPermission(MainActivity2.this, Manifest.permission.ACCESS_FINE_LOCATION)
                        != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(MainActivity2.this,
                            new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                            REQ_LOC_CODE);

                } else {
                    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, MainActivity2.this);
                    //locationManager.removeUpdates(MainActivity.this);
                }
                //locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
                //   0, 0, MainActivity.this);

                //locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER., 0, 0 , MainActivity.this);

            }
        });
    }
    //energopoietai apo to kleisimou tou dangerous permissions
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQ_LOC_CODE && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
                    != PackageManager.PERMISSION_GRANTED) {

                return;
            }
            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, MainActivity2.this);
        }
    }
 @Override
    public void onLocationChanged(@NonNull Location location) {
        //sintetagmenes sto text
        x=location.getLatitude();
        y=location.getLongitude();
        
        textView3.setText(String.format("Your current location  is:X=%.2f",x));
        textView21.setText(String.format(" and Y=%.2f",y));
    
        textspeech.speak("Your current location is:"+"X="+String.format("%.2f",x)+","+"
"+"Y="+String.format("%.2f",y));


    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {

    }

    @Override
    public void onProviderEnabled(@NonNull String provider) {

    }

    @Override
    public void onProviderDisabled(@NonNull String provider) {

    }

textspeech 类代码

public class textspeech {
    private TextToSpeech tts;
    TextToSpeech.OnInitListener initListener=new TextToSpeech.OnInitListener() {
        @Override
        public void onInit(int status) {
            if(status==TextToSpeech.SUCCESS){
                tts.setLanguage(Locale.US);
            }
        }
    };
    //prepei na ftiaksume constructor moni mas gt h mixani omilias dn
    // mporei na energopoithi moni ths h klasi prepei na energopoiithoi apo contex
    public  textspeech(Context context){
        tts=new TextToSpeech(context, initListener);
    }
    //methodos gia na tn kalume
    public void speak(String message){
        tts.speak(message,TextToSpeech.QUEUE_ADD, null,null);
    }

}

修复方案

问题根源

  1. 定位更新持续触发:设置locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, ...)时,参数0,0表示只要位置有任何微小变化就会触发onLocationChanged,导致不断调用播报方法。
  2. 语音队列叠加:textspeech.speak方法用了TextToSpeech.QUEUE_ADD,每次触发都会把新的播报内容加到队列里,旧内容未播完新内容又进入,造成循环播报。

具体修复步骤

1. 控制定位更新逻辑

如果只需要点击按钮时获取一次位置,在拿到位置后立即移除监听:

@Override
public void onLocationChanged(@NonNull Location location) {
    // 获取并显示位置
    x=location.getLatitude();
    y=location.getLongitude();
    textView3.setText(String.format("Your current location  is:X=%.2f",x));
    textView21.setText(String.format(" and Y=%.2f",y));
    
    // 播报位置
    textspeech.speak("Your current location is: X="+String.format("%.2f",x)+", Y="+String.format("%.2f",y));
    
    // 移除定位监听,避免持续触发
    locationManager.removeUpdates(this);
}

如果需要持续更新但不想每次都播报,可以添加标记控制播报时机(比如只播报一次,或位置变化超过阈值时播报):

private boolean hasReportedLocation = false; // 类成员变量

@Override
public void onLocationChanged(@NonNull Location location) {
    x=location.getLatitude();
    y=location.getLongitude();
    textView3.setText(String.format("Your current location  is:X=%.2f",x));
    textView21.setText(String.format(" and Y=%.2f",y));
    
    // 仅播报一次
    if(!hasReportedLocation){
        textspeech.speak("Your current location is: X="+String.format("%.2f",x)+", Y="+String.format("%.2f",y));
        hasReportedLocation = true;
    }
}

2. 修改语音队列模式

把QUEUE_ADD改成QUEUE_FLUSH,新的播报内容会替换队列中未播放的内容,避免叠加:

// 在textspeech类的speak方法中修改
public void speak(String message){
    tts.speak(message,TextToSpeech.QUEUE_FLUSH, null,null);
}

3. 避免重复注册定位监听

在按钮点击时先移除旧的监听,再添加新的,防止重复触发:

ImageButtonLoc.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        if (ActivityCompat.checkSelfPermission(MainActivity2.this, Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(MainActivity2.this,
                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                    REQ_LOC_CODE);

        } else {
            // 先移除旧监听,防止重复注册
            locationManager.removeUpdates(MainActivity2.this);
            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, MainActivity2.this);
        }
    }
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 11:15:43