{"id":5,"date":"2015-02-08T06:20:22","date_gmt":"2015-02-08T06:20:22","guid":{"rendered":"https:\/\/boochlin.com\/?p=5"},"modified":"2026-09-16T09:54:26","modified_gmt":"2026-09-16T09:54:26","slug":"fmradio-%e9%96%8b%e7%99%bc%e7%ad%86%e8%a8%98-%ef%bc%88%e4%ba%8c%ef%bc%89-fmradiomain","status":"publish","type":"post","link":"https:\/\/boochlin.com\/?p=5","title":{"rendered":"FMRadio \u958b\u767c\u7b46\u8a18 \uff08\u4e8c\uff09- FMRadioMain"},"content":{"rendered":"<h2>FMRadioMain<\/h2>\n<h4><strong>LAYOUT<\/strong><\/h4>\n<p>\u00a0<\/p>\n<pre class=\"mermaid\">graph LR\n    UI[FMRadioMain UI] -->|\u63a7\u5236\u983b\u9053\/\u97f3\u91cf| Service[FMRadioService]\n    Service -->|AudioManager| HAL[Audio HAL \/ FM Tuner]\n    HAL -->|\u97f3\u8a0a\u786c\u9ad4\u6d41| Headset[3.5mm \u8033\u6a5f\u5929\u7dda \/ \u63da\u8072\u5668]<\/pre>\n<h2><\/h2>\n<h2>1.\u5e38\u7528class<\/h2>\n<h3><strong>NumberPicker<\/strong><\/h3>\n<p><a href=\"http:\/\/code.google.com\/p\/taketoma-android-number-picker\/\">http:\/\/code.google.com\/p\/taketoma-android-number-picker\/<\/a><\/p>\n<p>\u985e\u4f3c\u53ef\u8f38\u5165\u7684DIALOGUE,<\/p>\n<p><a href=\"http:\/\/blog.csdn.net\/barryhappy\/article\/details\/7363230\">http:\/\/blog.csdn.net\/barryhappy\/article\/details\/7363230<\/a><\/p>\n<p>****\u00a0****<\/p>\n<h3><strong>AudioManager<\/strong><\/h3>\n<p>\u7528\u65bc\u97f3\u91cf\u8abf\u6574<\/p>\n<pre><code class=\"hljs language-plaintext\">setVolumeControlStream(AudioManager.STREAM_FM);<\/code><\/pre>\n<p>\u8a2d\u5b9a\u6536\u97f3\u6a5f\u7684\u97f3\u91cf\u63a7\u5236\u7b56\u7565<\/p>\n<p>STREAM_FM IS A STREAM STRATGE \u00a0HAS 10 LEVEL VOLUME<\/p>\n<h3>**DisplayMetric **<\/h3>\n<p>\u53d6\u5f97\u87a2\u5e55\u7684\u76f8\u95dc\u8cc7\u8a0a\u985e\u5225<\/p>\n<p>\u85c9\u8457\u5e7e\u884c\u7a0b\u5f0f\u78bc\u4f86\u53d6\u5f97\u624b\u6a5f\u87a2\u5e55\u7684\u89e3\u6790\u5ea6\uff0c\u7576\u4e2d\u7684\u95dc\u9375\u70baDisplayMetrics\u985e\u5225\u61c9\u7528\u3002<\/p>\n<pre><code class=\"hljs language-java\"><span class=\"hljs-type\">DisplayMetrics<\/span> <span class=\"hljs-variable\">metrics<\/span> <span class=\"hljs-operator\">=<\/span> <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-title class_\">DisplayMetrics<\/span>();\n\ngetWindowManager().getDefaultDisplay().getMetrics(metrics);\n\n<span class=\"hljs-type\">TextView<\/span> <span class=\"hljs-variable\">TextView1<\/span> <span class=\"hljs-operator\">=<\/span> (TextView)findViewById(R.id.TextView01);\n\nTextView1.setText(<span class=\"hljs-string\">&quot;\u624b\u6a5f\u9280\u5e55\u5927\u5c0f\u70ba &quot;<\/span>+metrics.widthPixels+<span class=\"hljs-string\">&quot; X &quot;<\/span>+metrics.heightPixels);<\/code><\/pre>\n<p><a href=\"http:\/\/style77125tech.pixnet.net\/blog\/post\/16792883-%5Bandroid%5D-displaymetrics-%E5%8F%96%E5%BE%97%E6%89%8B%E6%A9%9F%E8%9E%A2%E5%B9%95%E5%A4%A7%E5%B0%8F\">http:\/\/style77125tech.pixnet.net\/blog\/post\/16792883-%5Bandroid%5D-displaymetrics-%E5%8F%96%E5%BE%97%E6%89%8B%E6%A9%9F%E8%9E%A2%E5%B9%95%E5%A4%A7%E5%B0%8F<\/a><\/p>\n<p>****\u00a0****<\/p>\n<h3><strong>LoadedDataAndState<\/strong><\/h3>\n<p>\u662fFMRadio2\u4e2d\u7368\u6709\u7269\u4ef6<\/p>\n<p>\u65bcFMRadio2\u4e2d\u70ba\u4fdd\u5b58service\u4e2d\u7684fm\u786c\u9ad4\u7684\u958b\u95dc\u6a5f\u72c0\u614b<\/p>\n<p>\u7269\u4ef6\u6703\u5728onRetainNonConfigurationInstance()\u968e\u6bb5\u6642\uff0c\u9032\u884c\u7d44\u614b\u5167\u5bb9\u4fdd\u5b58<\/p>\n<hr>\n<pre><code class=\"hljs language-java\"><span class=\"hljs-meta\">@override<\/span>\n\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-type\">object<\/span> <span class=\"hljs-title function_\">onretainnonconfigurationinstance<\/span><span class=\"hljs-params\">()<\/span>\n\n{\n\n    <span class=\"hljs-comment\">\/\/\u8fd9\u91cc\u9700\u8981\u4fdd\u5b58\u7684\u5185\u5bb9\uff0c\u5728\u5207\u6362\u65f6\u4e0d\u662fbundle\u4e86\uff0c\u6211\u4eec\u53ef\u4ee5\u76f4\u63a5\u901a\u8fc7object\u6765\u4ee3\u66ff<\/span>\n\n    <span class=\"hljs-keyword\">return<\/span> LoadedDataAndState;\n\n}<\/code><\/pre>\n<p><a href=\"http:\/\/chengbs.iteye.com\/blog\/1156167\">http:\/\/chengbs.iteye.com\/blog\/1156167<\/a>Q<\/p>\n<p>\u6bd4\u8f83onsaveinstancestate() \u4e0e onretainnonconfigurationinstance()\u5728\u4e0d\u540c\u9700\u6c42\u4e2d\u7684\u7528\u6cd5<\/p>\n<p>\u5f88\u591a\u7f51\u53cb\u53ef\u80fd\u77e5\u9053android\u6a2a\u7ad6\u5c4f\u5207\u6362\u65f6\u4f1a\u89e6\u53d1onsaveinstancestate\uff0c\u800c\u8fd8\u539f\u65f6\u4f1a\u4ea7\u751fonrestoreinstancestate\uff0c\u4f46\u662fandroid\u7684activity\u7c7b\u8fd8\u6709\u4e00\u4e2a\u65b9\u6cd5\u540d\u4e3aonretainnonconfigurationinstance\u548cgetlastnonconfigurationinstance\u8fd9\u4e24\u4e2a\u65b9\u6cd5\u3002<\/p>\n<p>onRetainNonCongigurationInstance<\/p>\n<p>\u5f53device configuration\u53d1\u751f\u6539\u53d8\u65f6\uff0c\u5c06\u4f34\u968fdestroying\u88ab\u7cfb\u7edf\u8c03\u7528\u3002\u901a\u8fc7\u8fd9\u4e2a\u65b9\u6cd5\u53ef\u4ee5\u50cfonsaveinstancestate()\u7684\u65b9\u6cd5\u4e00\u6837\u4fdd\u7559\u53d8\u5316\u524d\u7684activity state\uff0c\u6700\u5927\u7684\u4e0d\u540c\u5728\u4e8e\u8fd9\u4e2a\u65b9\u6cd5\u53ef\u4ee5\u8fd4\u56de\u4e00\u4e2a\u5305\u542b\u6709\u72b6\u6001\u4fe1\u606f\u7684object\uff0c\u5176\u4e2d\u751a\u81f3\u53ef\u4ee5\u5305\u542bactivity instance\u672c\u8eab\u3002\u65b0\u521b\u5efa\u7684activity\u53ef\u4ee5\u7ee7\u627f\u5927\u91cf\u6765\u81f3\u4e8eparent activity state\u4fe1\u606f\u3002<\/p>\n<p>\u7528\u8fd9\u4e2a\u65b9\u6cd5\u4fdd\u5b58activity state\u540e\uff0c\u901a\u8fc7getlastnonconfigurationinstance()\u5728\u65b0\u7684activity instance\u4e2d\u6062\u590d\u539f\u6709\u72b6\u6001\u3002<\/p>\n<p>\u65bcfmradio2\u4e2d\u5247\u662f\u8907\u5beb\u6210\u4fdd\u7559\u5e95\u5c64mservice\u662f\u5426\u555f\u52d5.\u6545\u8abf\u7528isFmOn();<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0<\/p>\n<h2>2.some method<\/h2>\n<pre><code class=\"hljs language-java\">mLinearLayout = (LinearLayout) findViewById(R.id.layout_panel);\n<span class=\"hljs-keyword\">if<\/span> (mLinearLayout != <span class=\"hljs-literal\">null<\/span>){\nmLinearLayout.setOnTouchListener(<span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-title class_\">OnTouchListener<\/span>() {\n<span class=\"hljs-comment\">\/\/do something}<\/span><\/code><\/pre>\n<p>\u6b64\u6bb5\u91dd\u5c0d\u518dPANEL\u4e0a\u7684\u6ed1\u52d5\u63d0\u4f9b\u983b\u9053\u5207\u63db\u7684\u529f\u80fd.\u6839\u64da\u79fb\u52d5\u8ddd\u96e2\u5207\u63db<\/p>\n<p>****\u00a0****<\/p>\n<h3>registerForContextMenu\uff08mMenuButton\uff09<\/h3>\n<p>\u5c07view\u7684\u9ede\u64ca\u5f8c\u6548\u679c\u9023\u7d50\u5230contextmenu<\/p>\n<p>****\u00a0****<\/p>\n<p>\u00a0<\/p>\n<h3><strong>filter()<\/strong><\/h3>\n<p>\u65bc\u6b64\u904e\u6ffe\u4e09\u7a2e\u60c5\u6cc1\u2026<\/p>\n<p>1.\u7576\u96fb\u8a71\u63a5\u901a\u5f8c\u4ee5\u53ca\u96fb\u8a71\u6b63\u5728\u60f3\u2026\u5fc5\u9808\u4f7f\u7528<strong>TelephonyManager<\/strong>\u9032\u884c<strong>getCallState\uff08\uff09\u78ba\u8a8d\u72c0\u614b<\/strong><\/p>\n<p>2.\u6c92\u6709\u63a5\u4e0a\u8033\u6a5f\u2026\u5fc5\u9808\u4f7f\u7528**(AudioManager) getSystemService(Context.AUDIO_SERVICE);<strong>\u78ba\u8a8d<\/strong>isWiredHeadsetOn()**\u78ba\u8a8d\u8033\u6a5f\u662f\u5426\u6234\u4e0a<\/p>\n<p>3.\u78ba\u8a8d\u662f\u5426\u70baAirPlaneMode()\u2026\u5fc5\u9808\u642d\u914d<\/p>\n<pre><code class=\"hljs language-plaintext\">isAirplaneModeEnabled\uff08\uff09\u2026\u88e1\u9762\u5be6\u4f5c\n \u00a0 Settings.System.getInt(context.getContentResolver(),\n \u00a0 Settings.System.AIRPLANE_MODE_ON) == 1;<\/code><\/pre>\n<p>\u78ba\u8a8d\u624b\u6a5f\u7cfb\u7d71\u72c0\u614b<\/p>\n<p>****\u00a0****<\/p>\n<p><strong>\u2190\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014divider\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014&gt;<\/strong><\/p>\n<h3><strong>isCallActive()<\/strong><\/h3>\n<p>\u5411mService\u78ba\u8a8d\u96fb\u8a71\u72c0\u614b<\/p>\n<p>\u500b\u4eba\u89ba\u5f97\u7684\u6709\u9ede\u591a\u6b64\u4e00\u8209\u2026\u53ef\u4ee5\u76f4\u63a5\u518dmain\u88e1\u9762\u9032\u884c\u00a0<strong>TelephonyManager<\/strong>.getCallState()<\/p>\n<p>****\u00a0****<\/p>\n<p><strong>\u2190\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014-divider\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2013&gt;<\/strong><\/p>\n<h3><strong>CreateFrequencyPickerDialog()<\/strong><\/h3>\n<p>\u5275\u9020\u9078\u64c7\u983b\u9053\u7684\u5c0d\u8a71\u6846<\/p>\n<pre><code class=\"hljs language-java\">AlertDialog.<span class=\"hljs-type\">Builder<\/span> <span class=\"hljs-variable\">builder<\/span> <span class=\"hljs-operator\">=<\/span> <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-title class_\">AlertDialog<\/span>.Builder(<span class=\"hljs-built_in\">this<\/span>);\n\nbuilder.setTitle(<span class=\"hljs-built_in\">this<\/span>.getString(R.string.menu_set_frequency));\n\n\u00a0\n\n<span class=\"hljs-type\">LayoutInflater<\/span> <span class=\"hljs-variable\">inflater<\/span> <span class=\"hljs-operator\">=<\/span> (LayoutInflater) <span class=\"hljs-built_in\">this<\/span>\n\n    .getSystemService(LAYOUT_INFLATER_SERVICE);\n\n<span class=\"hljs-type\">View<\/span> <span class=\"hljs-variable\">layout<\/span> <span class=\"hljs-operator\">=<\/span> inflater.inflate(R.layout.value_picker,\n\n    (ViewGroup) findViewById(R.id.layout_root));<\/code><\/pre>\n<p>\u9019\u5169\u500b\u6bd4\u8f03\u5e38\u7528\u5230<\/p>\n<p>****\u00a0\u6b64\u5916****\u91dd\u5c0d\u983b\u9053\u9078\u64c7\u4e0a\u4f5c\u4e9b\u9650\u5236\u2026\u7562\u7adf\u4e0d\u662f\u6bcf\u500b\u983b\u9053\u90fd\u80fd\u9078\u2026\u53ef\u80fd\u662f\u570b\u7c4d\u6216\u958b\u653e\u983b\u9053\u7684\u95dc\u4fc2<\/p>\n<p>\u56e0\u6b64****<\/p>\n<pre><code class=\"hljs language-plaintext\">FmConfig fmConfig = FmSharedPreferences.getFMConfiguration()<\/code><\/pre>\n<p>;<\/p>\n<p>\u53d6\u7684lower higher limitation,<\/p>\n<p>\u9084\u5fc5\u9808\u6839\u64da\u570b\u7c4d\u8abf\u6574<\/p>\n<pre><code class=\"hljs language-plaintext\">int countryCode = FmSharedPreferences.getCountry();<\/code><\/pre>\n<p>\u7d66\u4e88\u5c0d\u61c9\u7684string\u63d0\u793a<\/p>\n<p>****\u00a0****<\/p>\n<p><strong>\u2190\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014-divider\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2013&gt;<\/strong><\/p>\n<h3><strong>createRangeSettingsDialog\uff08\uff09<\/strong><\/h3>\n<p>\u7531\u65bc\u570b\u5bb6\u7684\u4e0d\u540c\u2026\u983b\u5bec\u958b\u653e\u7684\u4e5f\u4e0d\u540c\u2026\u6240\u4ee5\u63d0\u4f9b\u5207\u63db\u7684\u529f\u80fd<\/p>\n<p>\u5229\u7528<\/p>\n<pre><code class=\"hljs language-plaintext\">int countryCode = FmSharedPreferences.REGIONAL_BAND_AUTO;<\/code><\/pre>\n<p>\u4ee5\u53ca<strong>FmSharedPreferences.setCountry(countryCode);<\/strong><\/p>\n<p>\u5f9e\u65b0\u9032\u884cFmradio.service\u7684\u5f9e\u7d44<strong>fmConfigure();<\/strong><\/p>\n<p>\u00a0<\/p>\n<p><strong>\u2190\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014-divider\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2013&gt;<\/strong><\/p>\n<h3><strong>createProgressDialog()<\/strong><\/h3>\n<pre><code class=\"hljs language-plaintext\">boolean bSearchActive = isSeekActive() || isScanActive() ||isSearchActive();<\/code><\/pre>\n<p>\u78ba\u8a8dmService\u7684\u904b\u4f5c\u72c0\u614b \u7576\u9084\u6c92\u6709\u4efb\u4f55search\u76f8\u95dc\u7684\u52d5\u4f5c\u6703\u5275\u898b\u65b0\u7684dialog<\/p>\n<p>\u76ee\u524d\u662f\u5c08\u70ba isFirstRun\u800c\u8a2d\u8a08\u7684\u2026\u53ea\u6709\u6b64\u6642\u6703\u7528\u5230progress dialog<\/p>\n<p>****\u00a0****<\/p>\n<p><strong>\u2190\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014divider\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2013&gt;<\/strong><\/p>\n<h3><strong>createCmdXXXDlg()<\/strong><\/h3>\n<p>\u9019\u985e\u7686\u70ba\u539f\u751fmethod()<\/p>\n<p>\u70ba\u63d0\u4f9b\u5404\u7a2e\u8b66\u544a\u63d0\u793a<\/p>\n<p>****\u00a0****<\/p>\n<h3><strong>searchFavoriteChanel\uff08\uff09<\/strong><\/h3>\n<p>\u70ba\u63d0\u4f9b\u7d66favoriteChange\u4f7f\u7528\u2026\u7531\u65bc\u518d\u5207\u63db\u6211\u7684\u6700\u611b\u96fb\u53f0\u6642\u2026\u53ef\u80fd\u6703\u51fa\u73fe\u6b64\u6700\u611b\u96fb\u53f0\u4e26\u975e\u7576\u524dmService\u6240\u670d\u52d9\u7684\u5340\u6bb5\u2026\u56e0\u6b64\u6211\u5011\u5fc5\u9808\u5148\u53bb\u6aa2\u67e5\u4e0b\u4e00\u500b\u6216\u4e0a\u4e00\u500b\u6700\u611b\u96fb\u53f0\u662f\u5426\u5408\u4e4e\u6240\u9078\u64c7\u7684\u570b\u7c4d\u8207\u5340\u6bb5<\/p>\n<p>****\u00a0****<\/p>\n<p><strong>\u2190\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2013divider\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2013&gt;<\/strong><\/p>\n<h3><strong>enableRadioOnOffUI(false);<\/strong><\/h3>\n<p>\u65bc\u7a0b\u5f0f\u5224\u65b7\u662f\u5426\u6709\u5f85\u4e0a\u5929\u7dda<\/p>\n<p>enableRadioOnOffUI(false);<\/p>\n<p><code>\/\/ HDMI and FM concurrecny is not supported.<\/code><\/p>\n<p>\u4e26\u4e0d\u652f\u63f4\u540c\u6642\u6709fm and hdmi<\/p>\n<pre><code class=\"hljs language-plaintext\">if (isHdmiOn()) {\n\n    showDialog(DIALOG_CMD_FAILED_HDMI_ON);\n} else {\n    if (false == bindToService(this, osc)) {\n\n        Log.d(LOGTAG, \"onCreate: Failed to Start Service\");\n\n    } else {\n        Log.d(LOGTAG, \"onCreate: Start Service completed successfully\");\n    }\n}<\/code><\/pre>\n<p>****\u00a0****<\/p>\n<pre><code class=\"hljs language-java\"><span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-type\">boolean<\/span> <span class=\"hljs-title function_\">isHdmiOn<\/span><span class=\"hljs-params\">()<\/span> {\n<span class=\"hljs-comment\">\/\/ HDMI and FM concurrecny is not supported.<\/span>\n\n    <span class=\"hljs-keyword\">try<\/span> {\n        <span class=\"hljs-type\">String<\/span> <span class=\"hljs-variable\">hdmiUserOption<\/span> <span class=\"hljs-operator\">=<\/span> android.provider.Settings.System.getString(\n        getContentResolver(), <span class=\"hljs-string\">&quot;HDMI_USEROPTION&quot;<\/span>);\n        <span class=\"hljs-comment\">\/\/\u9019\u88e1\u6211\u8a66\u51fa\u4f86\u2026hdmiUserOption == null;<\/span>\n        \u9019\u6bb5code\u6c92\u6709\u610f\u7fa9\u963f,\u6c38\u70ba<span class=\"hljs-literal\">false<\/span>\n\n    } <span class=\"hljs-keyword\">catch<\/span> (Exception ex) {\n    }\n<span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-literal\">false<\/span>;\n}<\/code><\/pre>\n<p>****\u00a0****<\/p>\n<p><strong>\u2190\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2013divider\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2013&gt;<\/strong><\/p>\n<h3>bar\u983b\u9053\u97ff\u61c9<\/h3>\n<pre><code class=\"hljs language-java\"><span class=\"hljs-keyword\">private<\/span> View.<span class=\"hljs-type\">OnTouchListener<\/span> <span class=\"hljs-variable\">mShiftFineTuneFigureListener<\/span> <span class=\"hljs-operator\">=<\/span> <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-title class_\">View<\/span>.OnTouchListener() {\n\n<span class=\"hljs-meta\">@Override<\/span>\n\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-type\">boolean<\/span> <span class=\"hljs-title function_\">onTouch<\/span><span class=\"hljs-params\">(View v, MotionEvent event)<\/span> {\n\n\u9019\u88e1\u4e3b\u8981\u518d\u8655\u7406\u7576\u6ed1\u52d5\u5e95\u4e0bshiftbar\u6240\u5c0d\u61c9\u7684\u52d5\u4f5c\u2026\u539f\u672c\u60f3\u505a\u7965\u89e3\u7684\n\n\u6de1\u5927\u591a\u6578\u591a\u70ba\u5c0d\u8036\u9762\u7269\u4ef6\u7684\u4f4d\u5740\u8a08\u7b97\u2026\u56e0\u6b64\u4e0d\u591a\u63d0\u4e86\n\n\u6bcf\u6b21\u91cd\u8b80\u6642\u2026\u8acb\u81ea\u884c\u770b\u7a0b\u5f0f\u78bc<\/code><\/pre>\n<p>****\u00a0****<\/p>\n<p><strong>\u2190\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014-divider\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2013&gt;<\/strong><\/p>\n<h3>****\u00a0Handler Control****<\/h3>\n<pre><code class=\"hljs language-java\"><span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-type\">Handler<\/span> <span class=\"hljs-variable\">mEnableRadioHandler<\/span> <span class=\"hljs-operator\">=<\/span> <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-title class_\">Handler<\/span>();\n\n<span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-type\">Handler<\/span> <span class=\"hljs-variable\">mDisableRadioHandler<\/span> <span class=\"hljs-operator\">=<\/span> <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-title class_\">Handler<\/span>();\n\n<span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-type\">Runnable<\/span> <span class=\"hljs-variable\">mEnableRadioTask<\/span> <span class=\"hljs-operator\">=<\/span> <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-title class_\">Runnable<\/span>() {<\/code><\/pre>\n<p>\u9019\u4e09\u500b\u884c\u70ba\u975e\u5e38\u7c21\u55ae\u2026\u4e3b\u8981\u57f7\u884c\u4e00\u4e9bmService\u5df2\u7d93\u5b9a\u7fa9\u597d\u7684\u884c\u70ba\u2026\u7528handler\u5305\u8d77\u4f86\u5247\u662f\u53e6\u5916\u5fc5\u9808\u5c0dlayout\u7684\u63a7\u5236<\/p>\n<p>****\u00a0****<\/p>\n<p><strong>\u2190\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014-divider\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2013&gt;<\/strong><\/p>\n<h3>Search Progress control<\/h3>\n<pre><code class=\"hljs language-java\"><span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-type\">void<\/span> <span class=\"hljs-title function_\">resetSearchProgress<\/span><span class=\"hljs-params\">()<\/span> {\n\n<span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-type\">void<\/span> <span class=\"hljs-title function_\">updateSearchProgress<\/span><span class=\"hljs-params\">()<\/span> {<\/code><\/pre>\n<p>\u518d\u6211\u5011\u9032\u884cseek\u6642\u2026\u6703\u53bb\u547c\u53ebmService\u9032\u884c\u76f8\u95dc\u7684chanel search\u2026\u65bc\u6b64\u540c\u6642\u4e5f\u5fc5\u9808\u5c0dlayout\u9032\u884c\u756b\u9762\u66f4\u65b0.\u4e5f\u5c31\u662fsearchProgress\u7684\u986f\u793a\u2026\u9019\u7531\u65bc\u662f\u4fee\u6539\u524d\u4eba\u7684\u7a0b\u5f0f\u2026\u6240\u4ee5\u4e5f\u4fdd\u7559method\u7684\u547d\u540d\u203b\u4f46\u4e3b\u8981\u5df2\u7d93\u6c92\u6709progress bar\u7684\u5b58\u5728\u2026\u800c\u662fprogress txt\u7684\u66f4\u65b0<\/p>\n<p>\u6703\u767c\u51famSearchProgressHandler\u53bb\u8ddf\u65b0\u756b\u9762(msg.what = UPDATE_PROGRESS_TXT_1;)<\/p>\n<p>Scanning. \u00a0\u00a0-&gt; Scanning .. -&gt; Scanning\u2026<\/p>\n<p>(UPDATE_PROGRESS_TXT_1)(UPDATE_PROGRESS_TXT_2)(UPDATE_PROGRESS_TXT_3)<\/p>\n<p>search \u7d50\u675f\u5f8c \u767c\u51faEND_PROGRESS_TXT<\/p>\n<p>****\u00a0****<\/p>\n<p><strong>\u2190\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014-divider\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2013&gt;<\/strong><\/p>\n<h3>****\u00a0First Run Something****<\/h3>\n<pre><code class=\"hljs language-java\"><span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-type\">void<\/span> <span class=\"hljs-title function_\">FirstRunSeekNextStation<\/span><span class=\"hljs-params\">()<\/span> {\n<span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-type\">void<\/span> <span class=\"hljs-title function_\">updateFirstRunSearchProgress<\/span><span class=\"hljs-params\">()<\/span> {<\/code><\/pre>\n<p>\u61c9\u7528\u9918\u5730\u4e00\u6b21\u958b\u555fFMRADIO<\/p>\n<p>\u8ddf\u524d\u9762\u7684\u529f\u80fd\u5f88\u50cf\u2026\u4f46\u662f\u9019\u6b21\u4e0d\u662fUPDATE_PROGRESS_TXT_2\u2026\u800c\u662f\u5c0dmProgressDialog\u9015\u884c\u63a7\u5236<\/p>\n<p>****\u00a0****<\/p>\n<p>\u9019\u88e1\u6211\u8a8d\u70baFirstRunSeek\u8207\u975efirstrunSEEK\u5f88\u50cf<\/p>\n<p>\u6216\u8a31\u53ef\u4ee5\u4fee\u6539\u4e58\u66f4\u52a0\u7cbe\u7c21\u2026\u7562\u7adf\u884c\u70ba\u5f88\u50cf<\/p>\n<p>\u53ef\u662f\u9019\u6a23\u7e6a\u5f71\u60f3\u5230\u53ef\u8b80\u6027<\/p>\n<p>****\u00a0****<\/p>\n<p>\u6240\u4ee5\u5148\u4fdd\u6301\u9019\u6a23\u597d\u4e86<\/p>\n<p><strong>\u2190\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014-divider\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2013&gt;<\/strong><\/p>\n<h3>UI Update<\/h3>\n<pre><code class=\"hljs language-java\"><span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-type\">void<\/span> <span class=\"hljs-title function_\">updateStationInfoToUI<\/span><span class=\"hljs-params\">()<\/span> {\n<span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-type\">void<\/span> <span class=\"hljs-title function_\">updateFineTuneUI<\/span><span class=\"hljs-params\">()<\/span> {<\/code><\/pre>\n<p>\u57fa\u672c\u4e0a\u4efb\u4f55\u53ef\u80fd\u7684\u884c\u70ba\u203b\u90fd\u6703\u78b0\u5230\u4fee\u6539LAYOUT\u7684\u60c5\u6cc1<\/p>\n<p>****\u00a0****<\/p>\n<p><strong>\u2190\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014divider\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2013&gt;<\/strong><\/p>\n<h3>SeekSomething<\/h3>\n<pre><code class=\"hljs language-java\"><span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-type\">void<\/span> <span class=\"hljs-title function_\">SeekPreviousStation<\/span><span class=\"hljs-params\">()<\/span> {\n\n<span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-type\">void<\/span> <span class=\"hljs-title function_\">SeekNextStation<\/span><span class=\"hljs-params\">()<\/span> {<\/code><\/pre>\n<p>Seek\u57fa\u672c\u4e0a\u5c31\u662f\u79fb\u52d5\u5230\u4e0b\u4e00\u500b\u5177\u6709\u6548\u529b\u7684\u96fb\u53f0<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0<\/p>\n<p><strong>\u2190\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014-divider\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2013&gt;<\/strong><\/p>\n<h3>Animation for seek<\/h3>\n<hr>\n<pre><code class=\"hljs language-java\"><span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-type\">int<\/span> <span class=\"hljs-variable\">UPDATE_PROGRESS_TXT_1<\/span> <span class=\"hljs-operator\">=<\/span> <span class=\"hljs-number\">1<\/span>; \u00a0\u00a0<span class=\"hljs-comment\">\/\/three type for scanning anim<\/span>\n\n \u00a0\u00a0\u00a0<span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-type\">int<\/span> <span class=\"hljs-variable\">UPDATE_PROGRESS_TXT_2<\/span> <span class=\"hljs-operator\">=<\/span> <span class=\"hljs-number\">2<\/span>;\n\n \u00a0\u00a0\u00a0<span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-type\">int<\/span> <span class=\"hljs-variable\">UPDATE_PROGRESS_TXT_3<\/span> <span class=\"hljs-operator\">=<\/span> <span class=\"hljs-number\">3<\/span>;\n\n \u00a0\u00a0\u00a0<span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-type\">int<\/span> <span class=\"hljs-variable\">END_PROGRESS_TXT<\/span> <span class=\"hljs-operator\">=<\/span> <span class=\"hljs-number\">4<\/span>;\n\n \u00a0\u00a0\u00a0<span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-type\">int<\/span> <span class=\"hljs-variable\">TIMEOUT_PROGRESS_DLG<\/span> <span class=\"hljs-operator\">=<\/span> <span class=\"hljs-number\">5<\/span>;\n\n \u00a0\u00a0\u00a0<span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-type\">int<\/span> <span class=\"hljs-variable\">FIRSTRUN_UPDATE_PROGRESS_DLG<\/span> <span class=\"hljs-operator\">=<\/span> <span class=\"hljs-number\">6<\/span>;\n\n \u00a0\u00a0\u00a0<span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-type\">int<\/span> <span class=\"hljs-variable\">FIRSTRUN_END_PROGRESS_DLG<\/span> <span class=\"hljs-operator\">=<\/span> <span class=\"hljs-number\">7<\/span>;\n\n \u00a0\u00a0\u00a0<span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-type\">int<\/span> <span class=\"hljs-variable\">SHOWBUSY_TIMEOUT<\/span> <span class=\"hljs-operator\">=<\/span> <span class=\"hljs-number\">300000<\/span>;\n\n \u00a0\u00a0\u00a0<span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-type\">Handler<\/span> <span class=\"hljs-variable\">mSearchProgressHandler<\/span> <span class=\"hljs-operator\">=<\/span> <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-title class_\">Handler<\/span>() {<\/code><\/pre>\n<p>****\u00a0****<\/p>\n<p>\u6240\u6709\u5c0d\u65bcsearch\u6240\u9032\u884c\u7684\u756b\u9762\u8b8a\u52d5\u90fd\u5728\u6b64\u9664\u88e1<\/p>\n<p>\u8981\u6ce8\u610f\u7684\u662f \u00a0message\u4e4b\u9593\u7684\u4ea4\u4e92\u95dc\u4fc2\u2026\u6240\u4ee5\u5fc5\u9808\u6ce8\u610f\u8981<\/p>\n<p>mSearchProgressHandler.<strong>removeMessages<\/strong><\/p>\n<p>****\u00a0****<\/p>\n<p><strong>\u2190\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2013divider\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2013&gt;<\/strong><\/p>\n<h3><strong>History Station<\/strong><\/h3>\n<pre><code class=\"hljs language-java\"><span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-type\">void<\/span> <span class=\"hljs-title function_\">addHistoryStation<\/span><span class=\"hljs-params\">(PresetStation station)<\/span>{\n\n<span class=\"hljs-type\">follow<\/span> <span class=\"hljs-title function_\">tuneRadio<\/span><span class=\"hljs-params\">()<\/span>;mSearchComplete;mUpdateStationInfo<\/code><\/pre>\n<p>\u6709\u5e7e\u9805\u898f\u5247<\/p>\n<p>1.list\u6709\u91cd\u8907\u7684\u5247\u79fb\u52d5\u5230\u6700\u4e0a\u9762\u4e00\u500b<\/p>\n<p>2.\u6c92\u6709\u91cd\u5fa9\u5247\u653e\u5728\u5730\u4e00\u500b<\/p>\n<p>3.list\u5167\u7e3d\u6578\u4e0d\u5f97\u8d85\u904e10\u500b<\/p>\n<p>****\u00a0****<\/p>\n<p>\u70ba\u4f55\u8981mSearchComplete.mUpdateStationInfo\u90fd\u52a0\u4e00\u500b<strong>addHistoryStation<\/strong><\/p>\n<p><strong>\u5982\u679c\u53ea\u5728searchcomplete\u5f8c\u52a0\u5165<\/strong><\/p>\n<p>\u4e3b\u8981\u5728\u65bcmSearchComplete\u548cmUpdateStationInfo\u662f\u4e0d\u540c\u7684THREAD<\/p>\n<p>\u5728searchComplete\u4e4b\u5f8c\u53bb\u8ddf\u5fc3\u756b\u9762resetFMStationInfoUI\uff08\uff09<\/p>\n<p>\u800c\u540c\u6642\u548cmUpdateStationInfo by onTuneStatusChanged()\u4e5f\u5728\u904b\u884c<\/p>\n<p>\u518dsearch\u6642\u9593\u6975\u77ed\u4e0b\u2026\u6709\u53ef\u80fdonTuneStatusChanged\u6703\u5148\u5b8c\u6210<\/p>\n<p>mTunedStation\u4e26\u6c92\u6709\u88ab\u8ddf\u65b0\u6210searchcomplete\u5f8c\u7684\u7d50\u679c<\/p>\n<p>\u6b64\u6642searchcomplete\u5c31\u4e0d\u6703\u5c07\u6700\u65b0\u7684history station \u52a0\u5165<\/p>\n<p>****\u00a0****<\/p>\n<p>\u6240\u4ee5\u5728\u5169\u908a\u90fd\u52a0\u5165addhistorystation\u6703\u6bd4\u8f03\u597d<\/p>\n<p>\u907f\u514d\u5b8c\u6210\u6642\u9593\u5deeresetFMStationInfoUI();<\/p>\n<p>****\u00a0****<\/p>\n<p><strong>\u2190\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2013divider\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2013&gt;<\/strong><\/p>\n<p>****\u00a0****<\/p>\n<pre><code class=\"hljs language-java\"><span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-type\">void<\/span> <span class=\"hljs-title function_\">tuneRadio<\/span><span class=\"hljs-params\">(<span class=\"hljs-type\">int<\/span> frequency)<\/span> {<\/code><\/pre>\n<p>\u7576\u6539\u8b8a\u5f8c\u90fd\u6703\u547c\u53eb\u2026\u63a5\u8005\u5f8c\u9762\u8ddf\u8005\u8981\u52a0\u5165\u6b77\u53f2\u96fb\u53f0<\/p>\n<p>\u8b93mService\u53bb\u64ad\u653e\u96fb\u53f0\u2026..\u5927\u6982\u662f\u6700\u5e38\u7528\u7684\u529f\u80fd<\/p>\n<p>****\u00a0****<\/p>\n<p><strong>\u2190\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2013divider\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2013&gt;<\/strong><\/p>\n<p><strong>final Runnable mSearchListComplete = new Runnable() {<\/strong><\/p>\n<p>\u7b49\u50f9\u65bc\u6240\u8b02\u7684ScanComplete<\/p>\n<p>****\u00a0****<\/p>\n<p><strong>\u2190\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014-divider\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2013&gt;<\/strong><\/p>\n<p><strong>private IFMRadioServiceCallbacks.Stub mServiceCallbacks = new IFMRadioServiceCallbacks.Stub() {<\/strong><\/p>\n<p>** \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0public void onEnabled() {**<\/p>\n<p>****<a href=\"https:\/\/docs.google.com\/document\/d\/1eZwGVfXnpBE5K8m-QjJdsHEvRdinKjbvE7XTffSGiEA\/edit\">\u4e3b\u8981\u95dc\u65bcaidl\u7684bindservice\u7684\u6a5f\u5236<\/a><\/p>\n<p>\u00a0<\/p>\n<pre><code class=\"hljs language-java\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-type\">boolean<\/span> <span class=\"hljs-title function_\">bindToService<\/span><span class=\"hljs-params\">(Context context, ServiceConnection callback)<\/span><\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>FMRadioMain LAYOUT \u00a0 graph LR UI[FMRadioMain UI] &#8211;>|\u63a7\u5236 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[167],"tags":[190,221,243],"_links":{"self":[{"href":"https:\/\/boochlin.com\/index.php?rest_route=\/wp\/v2\/posts\/5"}],"collection":[{"href":"https:\/\/boochlin.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/boochlin.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/boochlin.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/boochlin.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=5"}],"version-history":[{"count":5,"href":"https:\/\/boochlin.com\/index.php?rest_route=\/wp\/v2\/posts\/5\/revisions"}],"predecessor-version":[{"id":1433,"href":"https:\/\/boochlin.com\/index.php?rest_route=\/wp\/v2\/posts\/5\/revisions\/1433"}],"wp:attachment":[{"href":"https:\/\/boochlin.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=5"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/boochlin.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=5"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/boochlin.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=5"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}