Linux手機DIY.Shell應用擴充一.隨機來電鈴聲(E680系列)
草木瓜
2007-03-18
一、什麼是Shell
在開始正題前,總習慣於從網上抄一些東東,來“豐富”下文章的內容。
Shell是一種具備特殊功能的程式,它是介於使用者和 UNIX/Linux 作業系統核
心程式(kernel)間的一個介面。換而言之,就是你平常要想操作 UNIX/Linux 的話,
就需要通過Shell來進行。
為什麼我們說 Shell 是一種介於系統核心程式與使用者間的中介者呢?讀過操
作系統概論的讀者們都知道作業系統是一個系統資源的管理者與分配者,當使用者有請
求時,得向系統提出;從作業系統的角度來看,它也必須防止使用者因為錯誤的操作
而造成系統的損害。眾所周知,對電腦系統下命令得通過預定義的命令或程式。
Shell本身就是一個程式,一個已經由別人寫好並且編譯過的程式,它從輸入設
備讀取命令,將其轉換為電腦作業系統可以理解的機器碼,然後執行。
各種作業系統其實都有它自己的Shell,以大家容易理解的DOS為例,它的Shell
就是command.com檔案。Windows下的DOS命令dir,copy等之類都是通過其解釋執行
的。
Unix/Linux系統下Shell也有多種。常用的有Bourne Shell(sh)、C-Shell
(csh)、Korn Shell(ksh)和Bourne Again Shell(bash)。
Bourne Shell(sh)是AT&T Bell實驗室的Steven Bourne為AT&T的Unix開發的,
它是Unix的預設Shell,也是其它Shell的開發基礎。Bourne Shell在編程方面相當
優秀,但在處理與使用者的互動方面不如其它幾種Shell。
C Shell(csh)是加州伯克利大學的Bill Joy為BSD Unix開發的,與sh不同,它
的文法與C語言很相似。它提供了Bourne Shell所不能處理的使用者互動特徵,如命令
補全、命令別名、曆史命令替換等。但是,C Shell與BourneShell並不相容。
Korn Shell(ksh)是AT&T Bell實驗室的David Korn開發的,它集合了C Shell
和Bourne Shell的優點,並且與Bourne Shell向下完全相容。Korn Shell的效率很
高,其命令互動介面和編程互動介面都很好。
Bourne Again Shell(bash)是自由軟體基金會(GNU)開發的一個Shell,它是Linux
系統中一個預設的Shell。Bash不但與Bourne Shell相容,還繼承了C Shell、Korn
Shell等眾多優點。
<Linux手機DIY系列:http://blog.csdn.net/liwei_cmg/category/241839.aspx>
二、隨機來電鈴音的總體思路
隨機來電鈴這東西早就有人實現,方法也是多種多樣的。具體這個東西的作用是
仁者見仁,智者見智。個人覺得偶爾用用感覺也不錯,重要的是挖掘Shell擴充手機
應用的潛力。而且Shell對大多數人來說,上手也比較容易,相關資料也十分多。夏新
E600和飛利浦968的安裝包就是通過簡單的一些Shell來實現。可以說,研究這些手機
最為關鍵的部分,就是Shell!
現在大多數Linux智能手機,鈴音配置都是以文字格式設定存在,可見理論上直接修改
這類檔案就可以輕鬆實現對簡訊息和手機鈴聲變更。但在實際操作過程中發現,直
接去修改這個檔案的話,E680是不能夠即時生效的,需要重新設定重新整理才行。
後經一些嘗試發現,先設定好鈴音的設定檔,修改實際的對應鈴聲檔案最為有效。
AlertRingTone1 = /mmc/mmca1/Music/Ring/ring.mp3
AlertRingTone2 = /mmc/mmca1/Music/Ring/ring.mp3
AlertRingerIDs = 0
AlertStyleIconDir = /usr/language/alertStyle/
AlertSystemVolume = 10
AlertTextMsg = /mmc/mmca1/Music/Ring/message.mp3
[AlertTextMsg]對應簡訊息鈴聲,[AlertRingTone1]對應來電鈴聲,這個配置文
件我不去改它,動態修改的是ring.mp3,message.mp3的實際檔案。修改的過程僅僅就是
mv Artist.mp3 ring.mp3這麼簡單。
下面需要解決的就是修改時機和隨即性兩個問題。我這裡顯然是一個在後台不斷循
環啟動並執行Shell指令碼,當簡訊息或者來電時,系統會啟動alterprocss這個進程,這個腳
本自然能檢測的這個進程相關資訊,並修改相應的鈴聲檔案。至於隨機性,其實來電本
身就是隨機事件,這裡只用了一個偽隨機方法,即根據來電的時間資訊,進行鈴聲檔案
選擇。
三、指令檔全內容
001 #!/bin/bash
002
003
004 #當前路徑
005 Path_Current=/mmc/mmca1/soft/ring
006
007 #記錄檔
008 File_Log=$Path_Current/log.txt
009
010 #來電鈴聲目錄
011 if [ ! -f $Path_Current/ring.txt ]
012 then
013 echo /mmc/mmca1/Music/Game > $Path_Current/ring.txt
014 fi
015 Path_Ring=`cat $Path_Current/ring.txt`
016
017 #簡訊息鈴聲目錄
018 if [ ! -f $Path_Current/msg.txt ]
019 then
020 echo /mmc/mmca1/Music/Game > $Path_Current/msg.txt
021 fi
022 Path_Message=`cat $Path_Current/msg.txt`
023
024 #固定來電訊息檔案目錄
025 if [ ! -f $Path_Current/default.txt ]
026 then
027 echo /mmc/mmca1/Music/Ring > $Path_Current/default.txt
028 IsReset=1
029 else
030 IsReset=0
031 fi
032 Path_Default=`cat $Path_Current/default.txt`
033
034
035 #系統預定義簡訊最長秒
036 if [ ! -f $Path_Current/maxmessage.txt ]
037 then
038 echo "15" > $Path_Current/maxmessage.txt
039 fi
040 Var_MsgMaxSecond=`cat $Path_Current/maxmessage.txt`
041
042 #指定的短訊息鈴聲
043 Default_MessageFile=$Path_Default/message.mp3
044 #指定的電話鈴聲
045 Default_RingFile=$Path_Default/ring.mp3
046
047
048 #指令集
049 File_Busybox=/mmc/mmca1/tmp/busybox
050 #臨時處理配置的檔案
051 File_Sed=$Path_Current/tmpsed.txt
052 #臨時檔案大聲
053 File_TmpRingLoud=$Path_Current/tmpRingLoud.pts
054 #臨時檔案輕聲
055 File_TmpRingSoft=$Path_Current/tmpRingSoft.pts
056
057 #臨時進程檔案
058 File_TmpProcess=$Path_Current/tmpgrep.txt
059
060
061 #臨時可供隨機的檔案清單
062 FileList_Tmp=filelist.txt
063
064 #系統大聲的設定檔
065 File_RingLoud=/ezxlocal/download/appwrite/setup/RingLoud.pts
066 #系統輕聲的設定檔
067 File_RingSoft=/ezxlocal/download/appwrite/setup/RingSoft.pts
068
069
070 echo "====== Random Ring ======" >> $File_Log
071 echo `$File_Busybox date` " : Start" >> $File_Log
072
073
074 if [ "$IsReset" = "1" ]
075 then
076
077 echo `$File_Busybox date` " : Create New PtsFile" >> $File_Log
078
079 #產生新的設定檔
080 echo "#!/bin/sed -f" > $File_Sed
081 echo "/AlertRingTone1/ c//" >> $File_Sed
082 echo "AlertRingTone1 = $Default_RingFile" >> $File_Sed
083 echo "/AlertRingTone2/ c//" >> $File_Sed
084 echo "AlertRingTone2 = $Default_RingFile" >> $File_Sed
085 echo "/AlertTextMsg/ c//" >> $File_Sed
086 echo "AlertTextMsg = $Default_MessageFile" >> $File_Sed
087
088 #echo $File_Sed " " $File_RingLoud
089 $File_Sed $File_RingLoud > $File_TmpRingLoud
090 $File_Sed $File_RingSoft > $File_TmpRingSoft
091
092 cp -f $File_TmpRingLoud $File_RingLoud
093 cp -f $File_TmpRingSoft $File_RingSoft
094
095 fi
096
097 #$File_Busybox renice -20 $$
098 echo $$ > $Path_Current/proc.txt
099
100 echo `$File_Busybox date` " : ProcessID " $$ >> $File_Log
101
102 while
103
104 do
105
106 ProcID_Alert=`pidof alertprocess`
107
108 if [ "$ProcID_Alert" = "" ]
109 then
110
111 echo "Runing ..."
112 sleep 1s
113
114 else
115
116 echo `$File_Busybox date` " : AlertProcessID " $ProcID_Alert >> $File_Log
117
118 ps -ef | grep ".mp3" | grep -v grep > $File_TmpProcess
119
120 if grep "ring.mp3" $File_TmpProcess | grep -v grep
121 then
122 HaveSession="PHONE"
123 echo `$File_Busybox date` " : Have Phone " >> $File_Log
124 fi
125
126 if grep "message.mp3" $File_TmpProcess | grep -v grep
127 then
128 HaveSession="MESSAGE"
129 echo `$File_Busybox date` " : Have Message " >> $File_Log
130 fi
131
132 #迴圈變數
133 i=0
134
135 while [ ! "$ProcID_Alert" = "" ]
136 do
137 ProcID_Alert=`pidof alertprocess`
138 sleep 1s
139 #echo "sleep now!"
140
141 if [ "$HaveSession" = "MESSAGE" ]
142 then
143 if [ "$i" = "$Var_MsgMaxSecond" ]
144 then
145 kill -9 `pidof alertprocess`
146 else
147 i=$(($i+1))
148 fi
149 fi
150
151 done
152
153 Value_Base=`$File_Busybox date -u '+%M%S'`
154
155 #echo "OK"
156
157 if [ "$HaveSession" = "PHONE" ]
158 then
159
160 #處理隨機來鈴
161 cd $Path_Ring
162 rm $FileList_Tmp
163 find . -name '*[m,M][p,P]3' | sed 's/^.//g' > $FileList_Tmp
164 Max_Count=`$File_Busybox wc $FileList_Tmp | $File_Busybox awk '{print $1}'`
165 Value_Round=$(($Value_Base % $Max_Count + 1))
166
167 #echo $Value_Round
168
169 Name_NextRing=`sed -n "$Value_Round p" $Path_Ring/$FileList_Tmp`
170 rm $FileList_Tmp
171
172 if [ -f $Default_RingFile ]
173 then
174
175 if [ -f $Path_Current/prering.txt ]
176 then
177 #echo
178 mv "$Default_RingFile" "`cat $Path_Current/prering.txt`"
179 echo `$File_Busybox date` " : mv $Default_RingFile" "`cat $Path_Current/prering.txt`" >> $File_Log
180 else
181 rm "$Default_RingFile"
182 echo `$File_Busybox date` " : rm $Default_RingFile" >> $File_Log
183 fi
184
185 fi
186
187 #echo
188 mv "$Path_Ring$Name_NextRing" "$Default_RingFile"
189 echo $Path_Ring$Name_NextRing > $Path_Current/prering.txt
190 echo `$File_Busybox date` " : mv $Path_Ring$Name_NextRing" "$Default_RingFile" >> $File_Log
191
192 fi
193
194 if [ "$HaveSession" = "MESSAGE" ]
195 then
196
197 #處理隨機簡訊息
198 cd $Path_Message
199 rm $FileList_Tmp
200 find . -name '*[m,M][p,P]3' | sed 's/^.//g' > $FileList_Tmp
201 Max_Count=`$File_Busybox wc $FileList_Tmp | $File_Busybox awk '{print $1}'`
202 Value_Round=$(($Value_Base % $Max_Count + 1))
203
204 #echo $Value_Round
205
206 Name_NextMessage=`sed -n "$Value_Round p" $Path_Message/$FileList_Tmp`
207 rm $FileList_Tmp
208
209
210 if [ -f $Default_MessageFile ]
211 then
212
213 if [ -f $Path_Current/premsg.txt ]
214 then
215 #echo
216 mv "$Default_MessageFile" "`cat $Path_Current/premsg.txt`"
217 echo `$File_Busybox date` " : mv $Default_MessageFile" "`cat $Path_Current/premsg.txt`" >> $File_Log
218 else
219 rm "$Default_MessageFile"
220 echo `$File_Busybox date` " : rm $Default_MessageFile" >> $File_Log
221 fi
222
223 fi
224
225 #echo
226 mv "$Path_Message$Name_NextMessage" "$Default_MessageFile"
227 echo $Path_Message$Name_NextMessage > $Path_Current/premsg.txt
228 echo `$File_Busybox date` " : mv $Path_Message$Name_NextMessage" "$Default_MessageFile" >> $File_Log
229
230
231 #kill -9 `pidof alertprocess`
232 #cp -f $Path_Ring/$Name_NextRing
233
234 fi
235
236
237 sleep 1s
238
239 fi
240
241
242 done
四、指令檔說明
這個指令碼雖然有點注釋,但乍一看還是有點亂,這裡作一些補充。
指令碼主要分“變數定義和預先處理”<001-100>“主迴圈”<101-242>兩部分。
A.“變數定義和預先處理”
這個指令碼命名隨意,但是存放路徑必須與<005>所定義的路徑相同。(註:這裡也
完全可以用`pwd`來代替。)
指令碼運行後會在當前路徑下產生如下檔案:
log.txt 記錄整個作業記錄
ring.txt 記錄來電鈴音隨機播放的目錄,目前指令碼會包含該目錄的所有子
目錄
msg.txt 記錄簡訊息鈴音隨即選擇的目錄,同上
default.txt 記錄來電的固定檔案的目錄,
maxmessage.txt 記錄簡訊的最長響鈴時間
此外還產生了一些tmp的臨時檔案。
B.“主迴圈”
系統總會不斷執行<106>這條語句,經過一些嘗試,使用pidof效率是最高的,
否則後台一旦起了Shell,系統整體速度會略有減慢。
Shell進程運行後,一旦有來電,會自動執行<114>下面的內容,<118>-<130>
進行進程資訊提取,判斷是簡訊息還是來電。<132>-<151>是對簡訊的特別處理,
如超過最大響鈴時間,即終止響鈴。
<157>-<234>是對隨即鈴聲檔案的真正處理。即每次來電,將檔案mv,從而保
證下次響鈴的隨機性。
這個指令碼主要用了busybox,原因是系統的原來的功能比較有限。
五、後記
本指令碼涉及的命令是十分常見的:ps,sed,find,grep,date等,所要注意的是
E680是用bash,對於$(())的數值運算表達方式,其它shell並不能通用。
對於Linux手機新手來說,現在只需要一些耐心去消化指令碼所使用的Shell命令
和Shell規範。