接着看FM模块的其他几个次要的类的源码。这样来看FM上层的东西不是太多。

请看android\vendor\qcom\opensource\fm\fmapp2\src\com\caf\fmradio\Settings.java

protected void onCreate(BundlesavedInstanceState)

从FMRadio.java用使用Intent跳转携带参数过来,在onCreate获取携带数据。

  1. protected void onCreate(Bundle savedInstanceState) {
  2. super.onCreate(savedInstanceState);
  3. Intent intent = getIntent();
  4. if (intent != null) {
  5. mRxMode = intent.getBooleanExtra(RX_MODE, false);
  6. }
  7. mPrefs = new FmSharedPreferences(this);
  8. if (mPrefs != null) {
  9. setPreferenceScreen(createPreferenceHierarchy());
  10. }
  11. }

private PreferenceScreen createPreferenceHierarchy() 初始化创建收音机设置里显示控件

  1. private PreferenceScreen createPreferenceHierarchy() {
  2. int index = 0;
  3. if (mPrefs == null) {
  4. return null;
  5. }
  6. // Root
  7. PreferenceScreen root = getPreferenceManager().createPreferenceScreen(
  8. this);
  9.  
  10. summaryBandItems = getResources().getStringArray(
  11. R.array.regional_band_summary);
  12. chSpacingItems = getResources().getStringArray(
  13. R.array.channel_spacing_entries);
  14. mBandPreference = new ListPreference(this);
  15. mBandPreference.setEntries(R.array.regional_band_entries);
  16. mBandPreference.setEntryValues(R.array.regional_band_values);
  17. mBandPreference.setDialogTitle(R.string.sel_band_menu);
  18. mBandPreference.setKey(REGIONAL_BAND_KEY);
  19. mBandPreference.setTitle(R.string.regional_band);index = FmSharedPreferences.getCountry();
  20. Log.d(LOGTAG, "createPreferenceHierarchy: Country: " + index);
  21. // Get the preference and list the value.
  22. if ((index < 0) || (index >= summaryBandItems.length)) {
  23. index = 0;
  24. }
  25. mBandPreference.setValueIndex(index);
  26. root.addPreference(mBandPreference);
  27.  
  28. mChannelSpacingPref = new ListPreference(this);
  29. mChannelSpacingPref.setEntries(R.array.channel_spacing_entries);
  30. mChannelSpacingPref.setEntryValues(R.array.channel_spacing_val);
  31. mChannelSpacingPref.setDialogTitle(R.string.sel_chanl_spacing);
  32. mChannelSpacingPref.setTitle(R.string.chanl_spacing);
  33. mChannelSpacingPref.setKey(CHAN_SPACING_KEY);
  34.  
  35. mUserBandMinPref = new EditTextPreference(this);
  36. mUserBandMinPref.setKey(USER_DEFINED_BAND_MIN_KEY);
  37. mUserBandMinPref.setTitle(R.string.usr_def_band_min);
  38. mUserBandMinPref.getEditText().setInputType(InputType.TYPE_CLASS_NUMBER |
  39. InputType.TYPE_NUMBER_FLAG_DECIMAL);
  40. mUserBandMinPref.setDialogTitle(R.string.usr_def_band_min);
  41.  
  42. mUserBandMaxPref = new EditTextPreference(this);
  43. mUserBandMaxPref.setKey(USER_DEFINED_BAND_MAX_KEY);
  44. mUserBandMaxPref.setTitle(R.string.usr_def_band_max);
  45. mUserBandMaxPref.setDialogTitle(R.string.usr_def_band_max);
  46. mUserBandMaxPref.getEditText().setInputType(InputType.TYPE_CLASS_NUMBER |
  47. InputType.TYPE_NUMBER_FLAG_DECIMAL);
  48.  
  49. setBandSummary(index);
  50.  
  51. if (mRxMode) {
  52. // Audio Output (Stereo or Mono)
  53. summaryAudioModeItems = getResources().getStringArray(
  54. R.array.ster_mon_entries);
  55. mAudioPreference = new ListPreference(this);
  56. mAudioPreference.setEntries(R.array.ster_mon_entries);
  57. mAudioPreference.setEntryValues(R.array.ster_mon_values);
  58. mAudioPreference.setDialogTitle(R.string.sel_audio_output);
  59. mAudioPreference.setKey(AUDIO_OUTPUT_KEY);
  60. mAudioPreference.setTitle(R.string.aud_output_mode);
  61. boolean audiomode = FmSharedPreferences.getAudioOutputMode();
  62. if (audiomode) {
  63. index = 0;
  64. } else {
  65. index = 1;
  66. }
  67. Log.d(LOGTAG, "createPreferenceHierarchy: audiomode: " + audiomode);
  68. mAudioPreference.setSummary(summaryAudioModeItems[index]);
  69. mAudioPreference.setValueIndex(index);
  70.  
  71. // AF Auto Enable (Checkbox)
  72. mAfPref = new CheckBoxPreference(this);
  73. mAfPref.setKey(AUTO_AF);
  74. mAfPref.setTitle(R.string.auto_select_af);
  75. mAfPref.setSummaryOn(R.string.auto_select_af_enabled);
  76. mAfPref.setSummaryOff(R.string.auto_select_af_disabled);
  77. boolean bAFAutoSwitch = FmSharedPreferences.getAutoAFSwitch();
  78. Log.d(LOGTAG, "createPreferenceHierarchy: bAFAutoSwitch: "
  79. + bAFAutoSwitch);
  80. mAfPref.setChecked(bAFAutoSwitch);
  81. root.addPreference(mAfPref);
  82.  
  83. if(FMRadio.RECORDING_ENABLE) {
  84. summaryRecordItems = getResources().getStringArray(
  85. R.array.record_durations_entries);
  86. int nRecordDuration = 0;
  87. mRecordDurPreference = new ListPreference(this);
  88. mRecordDurPreference.setEntries(R.array.record_durations_entries);
  89. mRecordDurPreference.setEntryValues(R.array.record_duration_values);
  90. mRecordDurPreference.setDialogTitle(R.string.sel_rec_dur);
  91. mRecordDurPreference.setKey(RECORD_DURATION_KEY);
  92. mRecordDurPreference.setTitle(R.string.record_dur);
  93. nRecordDuration = FmSharedPreferences.getRecordDuration();
  94. Log.d(LOGTAG, "createPreferenceHierarchy: recordDuration: "
  95. + nRecordDuration);
  96. switch(nRecordDuration) {
  97. case FmSharedPreferences.RECORD_DUR_INDEX_0_VAL:
  98. index = 0;
  99. break;
  100. case FmSharedPreferences.RECORD_DUR_INDEX_1_VAL:
  101. index = 1;
  102. break;
  103. case FmSharedPreferences.RECORD_DUR_INDEX_2_VAL:
  104. index = 2;
  105. break;
  106. case FmSharedPreferences.RECORD_DUR_INDEX_3_VAL:
  107. index = 3;
  108. break;
  109. }
  110. // Get the preference and list the value.
  111. if ((index < 0) || (index >= summaryRecordItems.length)) {
  112. index = 0;
  113. }
  114. Log.d(LOGTAG, "createPreferenceHierarchy: recordDurationSummary: "
  115. + summaryRecordItems[index]);
  116. mRecordDurPreference.setSummary(summaryRecordItems[index]);
  117. mRecordDurPreference.setValueIndex(index);
  118. root.addPreference(mRecordDurPreference);
  119. }
  120. }
  121. mRestoreDefaultPreference = new Preference(this);
  122.           mRestoreDefaultPreference.setTitle(
  123.                                        R.string.settings_revert_defaults_title);
  124.           mRestoreDefaultPreference.setKey(RESTORE_FACTORY_DEFAULT);
  125.           mRestoreDefaultPreference
  126.                                 .setSummary(R.string.settings_revert_defaults_summary);
  127.           mRestoreDefaultPreference.setOnPreferenceClickListener(this);
  128.           root.addPreference(mRestoreDefaultPreference);
  129.           return root;
  130. }

public void clearStationList()清除显示列表的电台。

  1. public void clearStationList() {
  2. SharedPreferences sp = getSharedPreferences(FMRadio.SCAN_STATION_PREFS_NAME, 0);
  3. SharedPreferences.Editor editor = sp.edit();
  4. editor.clear();
  5. editor.commit();
  6. }

public void onSharedPreferenceChanged(SharedPreferencessharedPreferences, String key) ListPerences的监听事件,电台信息改变

  1. public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
  2. String key) {
  3. int mTunedFreq = 0;
  4. boolean bStatus = false;
  5. if (key.equals(REGIONAL_BAND_KEY)) {
  6. int curListIndex = FmSharedPreferences.getCurrentListIndex();
  7. PresetList curList = FmSharedPreferences.getStationList(curListIndex);
  8. String valueStr = sharedPreferences.getString(key, "");
  9. int index = 0;
  10. if(valueStr != null) {
  11. index = mBandPreference.findIndexOfValue(valueStr);
  12. }
  13. if((index < 0) || (index >= summaryBandItems.length)) {
  14. index = 0;
  15. mBandPreference.setValueIndex(0);
  16. }else if((index + 1) == summaryBandItems.length) {
  17. mChannelSpacingPref.setEnabled(true);
  18. }else {
  19. mChannelSpacingPref.setEnabled(false);
  20. }
  21. Log.d(LOGTAG, "onSharedPreferenceChanged: Country Change: "
  22. + index);
  23. FmSharedPreferences.setCountry(index);
  24. setBandSummary(index);
  25. sendSettingsChangedIntent(FM_BAND_CHANGED);
  26. if (curList != null) {
  27. curList.clear();
  28. }
  29. clearStationList();
  30. }else if(key.equals(CHAN_SPACING_KEY)) {
  31. int curListIndex = FmSharedPreferences.getCurrentListIndex();
  32. PresetList curList = FmSharedPreferences.getStationList(curListIndex);
  33. String valStr = mChannelSpacingPref.getValue();
  34. int index = 0;
  35. if(valStr != null) {
  36. index = mChannelSpacingPref.findIndexOfValue(valStr);
  37. }
  38. if ((index < 0) || (index >= chSpacingItems.length)) {
  39. index = 0;
  40. mChannelSpacingPref.setValueIndex(0);
  41. }
  42. mChannelSpacingPref.setSummary(chSpacingItems[index]);
  43. FmSharedPreferences.setChSpacing(2 - index);
  44. sendSettingsChangedIntent(FM_CHAN_SPACING_CHANGED);
  45. if(curList != null) {
  46. curList.clear();
  47. }
  48. clearStationList();}else if(key.equals(USER_DEFINED_BAND_MIN_KEY)) {
  49. String valStr = mUserBandMinPref.getText();
  50. double freq = 0;
  51. try {
  52. freq = Double.parseDouble(valStr) * 1000;
  53. }catch(NumberFormatException e) {
  54. e.printStackTrace();
  55. return;
  56. }
  57. max_freq = FmSharedPreferences.getUpperLimit();
  58. min_freq = FmSharedPreferences.getLowerLimit();
  59. if((freq > 0) && (freq < max_freq) && (freq >= 76000)) {
  60. FmSharedPreferences.setLowerLimit((int)freq);
  61. sendSettingsChangedIntent(FM_BAND_CHANGED);
  62. setBandSummary(summaryBandItems.length - 1);
  63. clearStationList();
  64. }else {
  65. Toast.makeText(this, getString(R.string.user_defind_band_msg),
  66. Toast.LENGTH_SHORT).show();
  67. } }else if(key.equals(USER_DEFINED_BAND_MAX_KEY)) {
  68. String valStr = mUserBandMaxPref.getText();
  69. double freq = 0;
  70. try {
  71. freq = Double.parseDouble(valStr) * 1000;
  72. }catch(NumberFormatException e) {
  73. e.printStackTrace();
  74. return;
  75. }
  76. min_freq = FmSharedPreferences.getLowerLimit();
  77. max_freq = FmSharedPreferences.getUpperLimit();
  78. if((freq > 0) && (freq > min_freq) && (freq <= 108000)) {
  79. FmSharedPreferences.setUpperLimit((int)freq);
  80. sendSettingsChangedIntent(FM_BAND_CHANGED);
  81. setBandSummary(summaryBandItems.length - 1);
  82. clearStationList();
  83. }else {
  84. Toast.makeText(this, getString(R.string.user_defind_band_msg),
  85. Toast.LENGTH_SHORT).show();
  86. }
  87. }else {
  88. if(mRxMode) { if (key.equals(AUTO_AF)) {
  89. boolean bAFAutoSwitch = mAfPref.isChecked();
  90. Log.d(LOGTAG, "onSharedPreferenceChanged: Auto AF Enable: "
  91. + bAFAutoSwitch);
  92. FmSharedPreferences.setAutoAFSwitch(bAFAutoSwitch);
  93. mPrefs.Save();
  94. sendSettingsChangedIntent(FM_AF_OPTION_CHANGED);
  95. }else if(key.equals(RECORD_DURATION_KEY)) {
  96. if(FMRadio.RECORDING_ENABLE) {
  97. String valueStr = mRecordDurPreference.getValue();
  98. int index = 0;
  99. if (valueStr != null) {
  100. index = mRecordDurPreference.findIndexOfValue(valueStr);
  101. }
  102. if ((index < 0) || (index >= summaryRecordItems.length)) {
  103. index = 0;
  104. mRecordDurPreference.setValueIndex(index);
  105. }
  106. Log.d(LOGTAG, "onSharedPreferenceChanged: recorddur: "
  107. + summaryRecordItems[index]);
  108. mRecordDurPreference.setSummary(summaryRecordItems[index]);
  109. FmSharedPreferences.setRecordDuration(index);
  110. }
  111. } else if (key.equals(AUDIO_OUTPUT_KEY)) {String valueStr = mAudioPreference.getValue();
  112. int index = 0;
  113. if (valueStr != null) {
  114. index = mAudioPreference.findIndexOfValue(valueStr);
  115. }
  116. if (index != 1) {
  117. if (index != 0) {
  118. index = 0;
  119. /* It shud be 0(Stereo) or 1(Mono) */
  120. mAudioPreference.setValueIndex(index);
  121. }
  122. }
  123. Log.d(LOGTAG, "onSharedPreferenceChanged: audiomode: "
  124. + summaryAudioModeItems[index]);
  125. mAudioPreference.setSummary(summaryAudioModeItems[index]);
  126. if (index == 0) {
  127. // Stereo
  128. FmSharedPreferences.setAudioOutputMode(true);
  129. }else {
  130. // Mono
  131. FmSharedPreferences.setAudioOutputMode(false);
  132. }
  133. mPrefs.Save();
  134. sendSettingsChangedIntent(FM_AUDIO_MODE_CHANGED);
  135. }
  136. }
  137. }
  138. if (mPrefs != null) {
  139. if(bStatus) {
  140. mPrefs.Save();
  141. }else {
  142. mTunedFreq = FmSharedPreferences.getTunedFrequency();
  143. if (mTunedFreq > FmSharedPreferences.getUpperLimit() ||
  144. mTunedFreq < FmSharedPreferences.getLowerLimit()) {
  145. FmSharedPreferences.setTunedFrequency(
  146. FmSharedPreferences.getLowerLimit());
  147. }
  148. mPrefs.Save();
  149. }
  150. }
  151. }

public boolean onPreferenceClick(Preferencepreference) 收音机恢复出厂设置监听事件,后fm播放状态显示对话框,调用restoreSettingsDefault()存入初始化数据。

  1. public boolean onPreferenceClick(Preference preference) {
  2. boolean handled = false;
  3. if (preference == mRestoreDefaultPreference) {
  4. showDialog(RESTORE_FACTORY_DEFAULT_INT);
  5. }
  6. return handled;
  7. }

ListPreferences属性注册:

  1. private void restoreSettingsDefault() {
  2. if (mPrefs != null) {
  3. if (Locale.getDefault().equals(Locale.CHINA)) {
  4. mBandPreference
  5. .setValueIndex(FmSharedPreferences.REGIONAL_BAND_CHINA);
  6. }else{
  7. mBandPreference
  8. .setValueIndex(FmSharedPreferences.REGIONAL_BAND_INDONESIA);
  9. }
  10. if (mRxMode) { mAudioPreference.setValueIndex(0);
  11. if (FMRadio.RECORDING_ENABLE) {
  12. mRecordDurPreference.setValueIndex(0);
  13. }
  14. mAfPref.setChecked(true);
  15. FmSharedPreferences.SetDefaults();
  16. }else {
  17. if (Locale.getDefault().equals(Locale.CHINA)) {
  18. FmSharedPreferences
  19. .setCountry(FmSharedPreferences.REGIONAL_BAND_CHINA);
  20. }else{FmSharedPreferences
  21. .setCountry(FmSharedPreferences.REGIONAL_BAND_INDONESIA);
  22. }
  23. }
  24. mPrefs.Save();
  25. }
  26. }

onResume()方法

  1. protected void onResume() {
  2. super.onResume();
  3. PreferenceScreen preferenceScreen = getPreferenceScreen();
  4. SharedPreferences sharedPreferences = null;
  5. if (preferenceScreen != null) {
  6. sharedPreferences = preferenceScreen.getSharedPreferences();
  7. }
  8. if (sharedPreferences != null) {
  9. sharedPreferences.registerOnSharedPreferenceChangeListener(this);
  10. }
  11. }

haredPreferences.registerOnSharedPreferenceChangeListener(this);进行注册

protected void onPause()方法

  1. protected void onPause() {
  2. super.onPause();
  3. PreferenceScreen preferenceScreen = getPreferenceScreen();
  4. SharedPreferences sharedPreferences = null;
  5. if (preferenceScreen != null) {
  6. sharedPreferences = preferenceScreen.getSharedPreferences();
  7. }
  8. if (sharedPreferences != null) {
  9. sharedPreferences.unregisterOnSharedPreferenceChangeListener(this);
  10. }
  11. }

sharedPreferences.unregisterOnSharedPreferenceChangeListener(this);卸载注册

private void setBandSummary(int index) 设置ListPreference控件选择地区频率范围后现实在控件上

  1. private void setBandSummary(int index) {
  2. if((index + 1) == summaryBandItems.length) {
  3. min_freq = FmSharedPreferences.getLowerLimit();
  4. max_freq = FmSharedPreferences.getUpperLimit();
  5. chan_spacing = FmSharedPreferences.getChSpacing();
  6. if(chan_spacing < 0) {
  7. chan_spacing = 0;
  8. }
  9. mBandPreference.setSummary(summaryBandItems[index] + "( "
  10. + (min_freq / 1000.0) +"Mhz To " + (max_freq / 1000.0) +
  11. "Mhz)");
  12. mChannelSpacingPref.setValueIndex(2 - chan_spacing);
  13. mChannelSpacingPref.setSummary(chSpacingItems[2 - chan_spacing]);
  14. mChannelSpacingPref.setEnabled(true);
  15. mUserBandMinPref.setEnabled(true);mUserBandMaxPref.setEnabled(true);
  16. mUserBandMinPref.setSummary((min_freq / 1000.0) + "Mhz");
  17. mUserBandMaxPref.setSummary((max_freq / 1000.0) + "Mhz");
  18. }else {
  19. mBandPreference.setSummary(summaryBandItems[index]);
  20. mChannelSpacingPref.setEnabled(false);
  21. mUserBandMinPref.setEnabled(false);
  22. mUserBandMaxPref.setEnabled(false);
  23. }
  24. }

private void displayToast(String msg)实现Toast提示

  1. private void displayToast(String msg) {
  2. Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
  3. }

private void sendSettingsChangedIntent(intaction)
发送广播action活动状态,

在FMRadio.java的registerFMSettingListner()方法接受(每次走
FMRadio.java的activity都会接受下广播)。

  1. private void sendSettingsChangedIntent(int action) {
  2. Intent intent = new Intent(ACTION_FM_SETTING);
  3. intent.putExtra("state", action);
  4. Log.d(LOGTAG, "Sending FM SETTING Change intent for = " + action);
  5. getApplicationContext().sendBroadcast(intent);
  6. }
  7.  
  8. 总结:比较简单,过一遍即可。

Android FM模块学习之四源码分析(3)的更多相关文章

  1. Android FM 模块学习之四 源码解析(1)

    Normal 0 7.8 磅 0 2 false false false EN-US ZH-CN X-NONE MicrosoftInternetExplorer4 前一章我们了解了FM手动调频,接下 ...

  2. Android FM模块学习之四源码解析(一)

    转自:http://blog.csdn.net/tfslovexizi/article/details/41516149?utm_source=tuicool&utm_medium=refer ...

  3. Android FM模块学习之四源码学习(2)

    前几章我们分析了FM模块的几个主要的类文件,今天要分析的是:FMTransceiver.java   // 某些工程中名称为FMRadioService.java public class FmTra ...

  4. Android Small插件化框架源码分析

    Android Small插件化框架源码分析 目录 概述 Small如何使用 插件加载流程 待改进的地方 一.概述 Small是一个写得非常简洁的插件化框架,工程源码位置:https://github ...

  5. socketserver模块使用与源码分析

    socketserver模块使用与源码分析 前言 在前面的学习中我们其实已经可以通过socket模块来建立我们的服务端,并且还介绍了关于TCP协议的粘包问题.但是还有一个非常大的问题就是我们所编写的S ...

  6. DotNetty网络通信框架学习之源码分析

    DotNetty网络通信框架学习之源码分析 有关DotNetty框架,网上的详细资料不是很多,有不多的几个博友做了简单的介绍,也没有做深入的探究,我也根据源码中提供的demo做一下记录,方便后期查阅. ...

  7. Android图片处理神器BitmapFun源码分析

    作为一名Android开发人员,相信大家对图片OOM的问题已经耳熟能详了,关于图片缓存和解决OOM的开源项目也是相当的多,被大家熟知的就是Universal_image_loader和Volley了, ...

  8. Android View事件分发-从源码分析

    View事件分发-从源码分析 学习自 <Android开发艺术探索> https://blog.csdn.net/qian520ao/article/details/78555397?lo ...

  9. [置顶] 【Android实战】----从Retrofit源码分析到Java网络编程以及HTTP权威指南想到的

    一.简介 接上一篇[Android实战]----基于Retrofit实现多图片/文件.图文上传中曾说非常想搞明白为什么Retrofit那么屌.最近也看了一些其源码分析的文章以及亲自查看了源码,发现其对 ...

随机推荐

  1. sql函数PadLeft与PadRight代码实例

    1.PadLeft函数向已知字符串左边补充字符,使整个字符串到达指定长度 CREATE FUNCTION PadLeft ( ),/*原始字符*/ @TotalLength int,/*总长度*/ ) ...

  2. CSS3之尖角标签

    如图所示,Tag标签的制作通常使用背景图片,现在用CSS3代码就能实现尖角效果(需浏览器支持CSS3属性). 运用CSS3样式实现尖角标签,只需要写简单的HTML结构和CSS样式. <p> ...

  3. 在caffe中使用hdf5的数据

    caffe默认使用的数据格式为lmdb文件格式,它提供了把图片转为lmdb文件格式的小程序,但是呢,我的数据为一维的数据,我也要分类啊,那我怎么办?肯定有办法可以转为lmdb文件格式的,我也看了一些源 ...

  4. JavaScipt的秘密花园

    对象使用和属性 JavaScript 中所有变量都可以当作对象使用,除了两个例外 null 和undefined. false.toString(); // 'false'[1, 2, 3].toSt ...

  5. Python学习笔记----序列共性

    序列操作符 作用seq[ind] 获得下标为ind 的元素seq[ind1:ind2] 获得下标从ind1 到ind2 间的元素集合seq * expr 序列重复expr 次seq1 + seq2 连 ...

  6. 关于strcpy和memcpy

    strcpy和memcpy都是标准C库函数,它们有下面的特点. strcpy提供了字符串的复制.即strcpy只用于字符串复制,并且它不仅复制字符串内容之外,还会复制字符串的结束符.已知strcpy函 ...

  7. 转-浅谈HTTP中Get与Post的区别

    Http定义了与服务器交互的不同方法,最基本的方法有4种,分别是GET,POST,PUT,DELETE.URL全称是资源描述符,我们可以这样认为:一个URL地址,它用于描述一个网络上的资源,而HTTP ...

  8. Hadoop技术内幕-第一章 阅读原代码前的准备

    1.1 源代码学习环境 1.1.1 基础软件的下载 JDK-http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads ...

  9. Windows Store App 关键帧动画

    关键帧动画和插值动画类似,同样可以根据目标属性值的变化产生相应的动画效果,不同的是,插值动画是在两个属性值之间进行渐变,而关键帧动画打破了仅通过两个属性值控制动画的局限性,它可以在任意多个属性值之间进 ...

  10. 编写HTML表单提交并接受数据信息(获取用户通过表单提交的内容)

    MyInfoForm.java package com.fxl; import java.io.IOException; import java.io.PrintWriter; import java ...