当前位置: 首页 > 知识库问答 >
问题:

根据图标播放天气声音

姬自强
2023-03-14

我刚刚完成了应用程序的天气图标的实现,现在我正在尝试根据应用程序显示的图标在应用程序上播放天气声音。经过长时间的深入研究,我震惊地发现,从来没有人在任何平台上问过类似的问题。

我对java词典的了解非常狭窄,即使花时间阅读和研究他们的样本,我也很难理解文档。即我找到了一个文档,我相信它与我在这里试图实现的目标相对应 https://docs.oracle.com/javase/8/docs/api/java/util/Map.html

这就解释了

V put(K key,
      V value)

将指定值与此地图中的指定键相关联。在这种情况下,我想用K作为图标,用V作为我的声音,但是我不知道如何应用它,所以我寻找了例子,看到了这个https://study.com/academy/lesson/the-java-dictionary-class-definition-example.html它提供的例子仍然不足以帮助我完成,我知道如果我试图自己解决这个问题,我会搞砸的,所以我决定在这里想出这个,看看是否有人能帮忙,我真的很感激。

按照API的说明,我正在使用https://openweathermap.org/weather-conditions.有9个主要的天气条件。

这些是我尝试根据图标播放声音的目标:

  • 如果城市显示clear_sky图标,请播放clear_sky_sound
    • 否则,如果它显示few_clouds图标,请播放few_clouds_sound
    • 否则,如果它显示scattered_clouds图标,请播放scattered_clouds_sound
    • 否则,如果显示broken_clouds,则播放broken_clouds_sound
    • 否则,如果它显示shower_rain图标,请播放shower_rain_sound
    • 否则,如果显示雨图标,则播放rain_sound
    • 否则,如果显示雷暴图标,则播放thunderstorm_sound
    • 否则,如果显示雪图标,则播放snow_sound
    • 否则,如果它显示雾状图标,请播放mist_sound。

    这是我的片段代码

    public class FirstFragment extends Fragment {
    
        private WeatherDataViewModel viewModel;
    
        MediaPlayer firstSound, secondSound, thirdSound, fourthSound, fifthSound, sixthSound, seventhSound, eightSound, ninethSound;
    
        public FirstFragment() {
    // Required empty public constructor
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
        // Inflate the layout for this fragment
            View rootView = inflater.inflate(R.layout.fragment_first, container, false);
        // For displaying weather data
            final TextView current_temp = rootView.findViewById(R.id.textView10);
            final TextView current_output = rootView.findViewById(R.id.textView11);
            final TextView rise_time = rootView.findViewById(R.id.textView25);
            final TextView set_time = rootView.findViewById(R.id.textView26);
            final TextView temp_out = rootView.findViewById(R.id.textView28);
            final TextView Press_out = rootView.findViewById(R.id.textView29);
            final TextView Humid_out = rootView.findViewById(R.id.textView30);
            final TextView Ws_out = rootView.findViewById(R.id.textView33);
            final TextView Visi_out = rootView.findViewById(R.id.textView34);
            final TextView Cloud_out = rootView.findViewById(R.id.textView35);
            final ImageView current_icon = rootView.findViewById(R.id.imageView6);
            final SwipeRefreshLayout realSwipe = rootView.findViewById(R.id.real_swipe);
    
    
        // Get our ViewModel instance
            viewModel = new ViewModelProvider(this).get(WeatherDataViewModel.class);
    
    
    
        // And whenever the data changes, refresh the UI
            viewModel.getWeatherDataLiveData().observe(getViewLifecycleOwner(), data -> {
    
                realSwipe.setOnRefreshListener(() -> {
                    // perform you action here for ex. add refresh screen code here
                    new Handler().postDelayed(() -> {
                        // this code is for stop refreshing icon, After 1000 ms automatically refresh icon will stop
                        realSwipe.setRefreshing(false);
                    }, 1000);
                });
    
                int drawableResource = -1; // here define default icon for example R.drawable.default_weather_icon
    
                if (data != null) {
                    current_temp.setVisibility(View.VISIBLE);
                    current_temp.setText(data.getMain().getTemp() + " ℃"); // for that you can use strings resource and templates more in https://developer.android.com/guide/topics/resources/string-resource.html#formatting-strings
                    current_output.setVisibility(View.VISIBLE);
                    current_output.setText(data.getWeather().get(0).getDescription());
                    rise_time.setVisibility(View.VISIBLE);
                    rise_time.setText(data.getSys().getSunrise() + " ");
                    set_time.setVisibility(View.VISIBLE);
                    set_time.setText(data.getSys().getSunset() + " ");
                    temp_out.setVisibility(View.VISIBLE);
                    temp_out.setText(data.getMain().getTemp() + " ℃");
                    Press_out.setVisibility(View.VISIBLE);
                    Press_out.setText(data.getMain().getPressure() + " hpa");
                    Humid_out.setVisibility(View.VISIBLE);
                    Humid_out.setText(data.getMain().getHumidity() + " %");
                    Ws_out.setVisibility(View.VISIBLE);
                    Ws_out.setText(data.getWind().getSpeed() + " Km/h");
                    Visi_out.setVisibility(View.VISIBLE);
                    Visi_out.setText(data.getVisibility() + " m");
                    Cloud_out.setVisibility(View.VISIBLE);
                    Cloud_out.setText(data.getClouds().getAll() + " %");
    
    // get actual weather.
    
                    String icon = data.getWeather().get(0).getIcon();
    
                    switch (icon) {
                        case "01d":
                        case "01n":
                            drawableResource = R.drawable.sun;
    
                            break;
                        case "02d":
                        case "021n":
                            drawableResource = R.drawable.few_clouds;
    
                            break;
                        case "03d":
                        case "03n":
                            drawableResource = R.drawable.scattered_clouds;
    
                            break;
                        case "04d":
                        case "04n":
                            drawableResource = R.drawable.broken_clouds;
    
                            break;
                        case "09d":
                        case "09n":
                            drawableResource = R.drawable.shower_rain;
    
                            break;
                        case "10d":
                        case "10n":
                            drawableResource = R.drawable.small_rain;
    
                            break;
                        case "11d":
                        case "11n":
                            drawableResource = R.drawable.thunderstorm;
    
                            break;
                        case "13d":
                        case "13n":
                            drawableResource = R.drawable.snow;
    
                            break;
                        case "50d":
                        case "50n":
                            drawableResource = R.drawable.mist;
                            break;
                    }
    
    
                    if (drawableResource != -1)
                        current_icon.setImageResource(drawableResource);
    
                } else {
                    Log.e("TAG", "No City found");
                    current_temp.setVisibility(View.GONE);
                    current_output.setVisibility(View.GONE);
                    rise_time.setVisibility(View.GONE);
                    set_time.setVisibility(View.GONE);
                    temp_out.setVisibility(View.GONE);
                    Press_out.setVisibility(View.GONE);
                    Humid_out.setVisibility(View.GONE);
                    Ws_out.setVisibility(View.GONE);
                    Visi_out.setVisibility(View.GONE);
                    Cloud_out.setVisibility(View.GONE);
                    Toast.makeText(requireActivity(), "No City found", Toast.LENGTH_SHORT).show();
                }
            });
    
            return rootView;
        }
    
        public void getWeatherData(String name) {
    // The ViewModel controls loading the data, so we just
    // tell it what the new name is - this kicks off loading
    // the data, which will automatically call through to
    // our observe() call when the data load completes
            viewModel.setCityName(name);
        }
    }
    

    编辑:

    DennisVA 通过提供一个我可以遵循的样本来帮助(我尝试了他的第二个建议),但是当我尝试它时,我得到了一些错误,我使用他评论部分的链接分享了这些错误。我决定赏金这篇文章以吸引更多关注,这样我就可以更多地朝着正确的方向前进。

共有2个答案

胡锋
2023-03-14
匿名用户

我会创建一个包装器,以便更容易地向UI显示内容

例如:

public class Weather{
   @DrawableRes
   private int icon; //Resource id of the drawable
   private String sound; //Name or path the the sound file

   public Weather(WeatherPojo pojo){
       switch(pojo.icon){
                case "01d":
                case "01n":
                    this.icon = R.drawable.sun;
                    this.sound = ...
       }

   }
}

这个类还可以包含一个< code>play(MediaPlayer播放器)方法

我注意到的其他一些事情:

  • 避免对字符串进行硬编码
  • 您可能想看看视图绑定,以减少大量丑陋的rootView.findViewById调用(https://developer.android.com/topic/libraries/view-binding)

编辑:

另一个可能更好的选择是创建某种 WeatherFactory 类或解析器,以生成抽象 Weather 类的子类,并让该抽象类包含用于播放媒体文件的代码:

public abstract class Weather{
     @DrawableRes
     private int iconResId;
     @RawRes 
     private int soundResId;

     protected Weather(@DrawableRes int iconResId, @RawRes int soundResId){
        this.iconResId = iconResId;
        this.soundResId = soundResId
     }

     public void playSound(MediaPlayer mediaPlayer, Context context){

        String assetFileDescriptor = context.resources.openRawResourceFd(soundResId);

        if(assetFileDescriptor == null)
             return;

        mediaPlayer.reset();
        mediaPlayer.setDataSource(assetFileDescriptor.fileDescriptor, 
        assetFileDescriptor.startOffset, assetFileDescriptor.declaredLength);
        mediaPlayer.prepareAsync();
     }
} 

public class Snow extends Weather{
      public Snow(){
          super(R.drawable.snow, R.raw.snow)
      }
}

现在,您可以在您的片段或viewModel中调用< code>snow.playSound(),并在抽象类中生成getters和setters,以获取drawable并显示它。

其他变量,例如描述也可以注入子类的构造函数中,或者u可以为不同类型的雪(LightSnow、HeavySnow…)扩展子类本身

注意:我还没有测试过这些代码,所以它可能需要在这里和那里进行一些更改

赫连琦
2023-03-14

MediaPlayer第一声、第二声、第三声、第四声、第五声、第六声、第七声、第八声、第九声;

在这里,您创建了 9 个 MediaPlayer 对象,并且从它们的名称和计数来看,与图标的数量完全相同;我意识到每个人都会处理某个图标的声音。

尽管,您只能使用单个Media普拉尔对象来播放您拥有的9种声音中的任何一种。把它想象成您的操作系统媒体播放器,您有一个单一的媒体播放器应用程序,您可以一次拖放任何媒体文件,并随时更改它,而无需更改应用程序本身。

只要您想一次播放一个媒体文件,这就有效;但是,如果要同时播放多个声音,则可能需要多个MediaPlayer对象。

因此,就像您的情况一样,您一次只有一个 if 条件,所以我假设您想一次播放一个文件;因此,您一次只有一个图标(由于 switch 语句),因此您需要将上面提到的代码片段更改为单个变量:

MediaPlayer mediaPlayer;

我对java词典的了解很窄,很难理解留档

一本字典(或者它是一张用java准确发音的地图),把它想象成一个电话簿:你知道人名(Key),需要得到相应的电话号码(Value);本例中的区别在于,在电话目录中,每个键/人只有一个唯一的值;但是在javaMap中,您可以有重复的值(即不止一个键/人可以拥有相同的值/电话号码)。

V put(K key,
     V value)

同样,在java中,键和值几乎可以是任何东西,这可以从(K

我想用K作为图标,V作为我的声音,但我不知道如何应用它

在共享的简单示例中,我并不认为您需要地图;由于声音资源与相应的图标drawable资源高度耦合,所以您可以像对待drawable一样对待声音原始文件。

因此,无论何时更改当前可绘制内容(即在switch语句中),都需要在switch语句中更改当前声音,假设它们与可绘制内容同名:

MediaPlayer mediaPlayer; // single MediaPlayer object

int drawableResource = -1; // here define default icon for example R.drawable.default_weather_icon
int soundResource = -1; // Default sound is nothing

String icon = data.getWeather().get(0).getIcon();
switch (icon) {
    case "01d":
    case "01n":
        drawableResource = R.drawable.sun;
        soundResource = R.raw.sun;
        break;
    case "02d":
    case "021n":
        drawableResource = R.drawable.few_clouds;
        soundResource = R.raw.few_clouds;

        break;
    case "03d":
    case "03n":
        drawableResource = R.drawable.scattered_clouds;
        soundResource = R.raw.scattered_clouds;

        break;
    case "04d":
    case "04n":
        drawableResource = R.drawable.broken_clouds;
        soundResource = R.raw.broken_clouds;

        break;
    case "09d":
    case "09n":
        drawableResource = R.drawable.shower_rain;
        soundResource = R.raw.shower_rain;

        break;
    case "10d":
    case "10n":
        drawableResource = R.drawable.small_rain;
        soundResource = R.raw.small_rain;

        break;
    case "11d":
    case "11n":
        drawableResource = R.drawable.thunderstorm;
        soundResource = R.raw.thunderstorm;

        break;
    case "13d":
    case "13n":
        drawableResource = R.drawable.snow;
        soundResource = R.raw.snow;

        break;
    case "50d":
    case "50n":
        drawableResource = R.drawable.mist;
        soundResource = R.raw.mist;
        break;
}


if (drawableResource != -1)
    current_icon.setImageResource(drawableResource);
    
    
if (soundResource != -1) {
    prepareMediaPlayer(soundResource);
}



// In FirstFragment:

private void prepareMediaPlayer(int resource) {
    // add track file
    mMediaPlayer = MediaPlayer.create(requireActivity(), resource);

    // listening to when the media file finishes playing so that we can release the resources
    mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
        @Override
        public void onCompletion(MediaPlayer mp) {
            if (mMediaPlayer != null) {
                mMediaPlayer.release();
            }
        }
    });
    
}

只要您想播放声音,只需调用<code>mMediaPlayer。start(),但确保提前调用prepareMediaPlayer()<-code>。

提示:如果你想使用地图,我建议你为天气创建一个POJO/Data类,这样我们就可以创建一个地图。

 类似资料:
  • 播放(播放音效/播放录音)

  • 问题内容: 我正在尝试使用pygame播放声音文件(.wav),但是当我启动它时却听不到任何声音。 这是代码: 我也尝试使用频道,但结果是一样的 问题答案: 您的代码在我的机器上可以正常运行(Mac OSX 10.5,Python 2.6.4,pygame 1.9.1)。您正在使用哪些OS,Python和pygame版本?您是否可以通过其他方式(例如,在Mac的终端上或在Windows控制台上,然

  • 问题内容: 以下代码为什么不播放声音?它为play()返回“ true”,但我听不到任何声音。 如果我改用以下代码,则可以听到声音。 OS X优胜美地10.10.3 Xcode 6.2 问题答案: 问题是,您的AVAudioPlayer是一个 局部变量 。因此,它会立即不复存在-在开始播放之前,更不用说完成播放了。 解决方案:改为将其设置为 属性 ,以使其 持久存在 。

  • 问题内容: 我正在Android上创建游戏,并且已经将这个问题搁置了一段时间,现在又回到了问题上。在我的游戏中,我有背景音乐,枪声,爆炸声等,而且我需要能够同时玩它们。现在,当我在SoundPool类上调用play时,当前正在播放的声音被打断,新的声音开始播放。下面是我的SoundManager类及其用法。任何帮助将不胜感激,因为这确实是我需要拥有如此多音效的第一款游戏。谢谢! …这是我如何使用该

  • 问题内容: 在Python中播放声音文件(.wav)的最简单方法是什么?最简单的说,我指的是最独立的平台,并且需要最少的依赖。pygame当然是一个选择,但听起来似乎有些过分。 问题答案: Snack Sound Toolkit可以播放wav,au和mp3文件。

  • 问题内容: 我正在尝试播放声音,但无法正常工作。 编辑1: 仍然行不通。 编辑2 :此代码有效。我的设备处于静音模式。 问题答案: 对您的代码进行了修改: Swift 3和Swift 4.1: