L'enregistrement d'appel/service de traitement! - Android

Bonjour,

Je travaille sur une solution pour Android qui va enregistrer les appels (à la fois et incomming) et permettra de traiter davantage de données enregistrées (à la fin de ma demande, pas d'audio-fichier de données sera retenu sur la mémoire du téléphone). J'ai mis en œuvre BroadcastReceiver avec PhoneStateListener.LISTEN_CALL_STATE qui démarre un service d'enregistrement si l'état est CALL_STATE_OFFHOOK. Alors en service, j'ai commencer un nouveau thread qui tente l'enregistrement d'un appel, et un autre BroadcastReceiver avec PhoneStateListener.LISTEN_CALL_STATE, qui appelle une méthode pour arrêter l'enregistrement si le téléphone de l'état est modifié à TelephonyManager.CALL_STATE_IDLE.

Le fichier audio créé est vide.
Exception est levée lors de l'enregistreur.méthode stop() dans mon service est appelé. Où est l'erreur? Que pouvais-je faire de mieux?

Première (autonome) BroadcastReceiver:

    package com.piotr.callerrecogniser;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
public class CallReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
MyPhoneStateListener phoneListener = new MyPhoneStateListener(context);
TelephonyManager telephony = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
telephony.listen(phoneListener, PhoneStateListener.LISTEN_CALL_STATE);
}
class MyPhoneStateListener extends PhoneStateListener {
public static final String tag = "CallerRecogniser - CallReceiver";
private Context context;
MyPhoneStateListener(Context c) {
super();
context = c;
}
public static final int NOTIFICATION_ID_RECEIVED = 0x1221;
@Override
public void onCallStateChanged(int state, String incomingNumber) {
SharedPreferences preferences = context.getSharedPreferences("CallReceiver", Context.MODE_PRIVATE);
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
break;
//If call is answered, run recording service. Also pass "phone_number" variable with incomingNumber to shared prefs, so service will be able to access that via shared prefs.
case TelephonyManager.CALL_STATE_OFFHOOK: //The call is answered
String phone_number = preferences.getString("phone_number",null);
Intent serv = new Intent(context,
CallRecordingService.class);
serv.putExtra("number", phone_number);
context.startService(serv);
break;          
//If phone is ringing, save phone_number. This is done because incomingNumber is not saved on CALL_STATE_OFFHOOK
case TelephonyManager.CALL_STATE_RINGING:
SharedPreferences.Editor editor = preferences.edit();
editor.putString("phone_number", incomingNumber);
editor.commit();
break;
}
}
}
}

Service:

package com.piotr.callerrecogniser;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.MediaRecorder;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
public class CallRecordingService extends Service implements Runnable {
CallerRecogniserDB database = new CallerRecogniserDB(this);
String phoneNumber;
MediaRecorder recorder;
private final Handler mHandler = new Handler();
private final BroadcastReceiver myCallStateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
MyPhoneStateListener phoneListener = new MyPhoneStateListener(
context);
TelephonyManager telephony = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
telephony.listen(phoneListener,
PhoneStateListener.LISTEN_CALL_STATE);
}
class MyPhoneStateListener extends PhoneStateListener {
private Context context;
MyPhoneStateListener(Context c) {
super();
context = c;
}
@Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
if (recording) {
NotificationManager mNotificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
Notification not;
not = new Notification(R.drawable.ic_launcher,
"Phone call being processed",
System.currentTimeMillis());
Intent notIntent = new Intent();
PendingIntent contentIntent = PendingIntent
.getActivity(context, 0, notIntent, 0);
not.setLatestEventInfo(context, "CallRecordingService",
"Notification from idle",
contentIntent);
mNotificationManager.notify(NOTIFICATION_ID_RECEIVED,
not);
stopRecording();
}
break;
}
}
}
};
private static boolean recording = false;
private String INCOMING_CALL_ACTION = "android.intent.action.PHONE_STATE";
@Override
public void onCreate() {
//TODO Auto-generated method stub
super.onCreate();
IntentFilter intentToReceiveFilter = new IntentFilter();
intentToReceiveFilter.addAction(INCOMING_CALL_ACTION);
this.registerReceiver(myCallStateReceiver, intentToReceiveFilter, null,
mHandler);
Thread aThread = new Thread(this);
aThread.start();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//TODO Auto-generated method stub
super.onStart(intent, startId);
phoneNumber = intent.getExtras().getString("number");
return START_STICKY;
}
@Override
public IBinder onBind(Intent arg0) {
//TODO Auto-generated method stub
return null;
}
public static final int NOTIFICATION_ID_RECEIVED = 0x1221;
@Override
public void run() {
Looper.myLooper();
Looper.prepare();
//TODO Auto-generated method stub
database.open();
String[] numbers = database.getData(CallerRecogniserDB.KEY_NUMBER);
int index = -1;
outside_for: for (int i = 0; i < numbers.length; i++) {
String[] splitted = numbers[i].split(",");
for (String nu : splitted) {
if (nu.equals(phoneNumber)) {
index = i;
break outside_for;
}
}
}
database.close();
if (index >= 0) { //Phone number is in a database and it's state==0 =>
//it has no data recorded
//Notification that call is recorded
recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/" + phoneNumber + ".3gp");
try {
recorder.prepare();
} catch (Exception e) {
e.printStackTrace();
}
recording = true;
recorder.start();
} 
}
void stopRecording() {
//Then clean up with when it hangs up:
recorder.stop();
recorder.release();
recording=false;
}
}

Autorisations:

<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Exception de sortie:

11-28 14:28:44.385: E/MediaRecorder(22438): stop called in an invalid state: 8
11-28 14:28:44.400: D/AndroidRuntime(22438): Shutting down VM
11-28 14:28:44.425: W/dalvikvm(22438): threadid=1: thread exiting with uncaught exception (group=0x4001e578)
11-28 14:28:44.435: E/AndroidRuntime(22438): FATAL EXCEPTION: main
11-28 14:28:44.435: E/AndroidRuntime(22438): java.lang.IllegalStateException
11-28 14:28:44.435: E/AndroidRuntime(22438):    at android.media.MediaRecorder.stop(Native Method)
11-28 14:28:44.435: E/AndroidRuntime(22438):    at com.piotr.callerrecogniser.CallRecordingService.stopRecording(CallRecordingService.java:159)
11-28 14:28:44.435: E/AndroidRuntime(22438):    at com.piotr.callerrecogniser.CallRecordingService$1$MyPhoneStateListener.onCallStateChanged(CallRecordingService.java:65)
11-28 14:28:44.435: E/AndroidRuntime(22438):    at android.telephony.PhoneStateListener$2.handleMessage(PhoneStateListener.java:369)
11-28 14:28:44.435: E/AndroidRuntime(22438):    at android.os.Handler.dispatchMessage(Handler.java:99)
11-28 14:28:44.435: E/AndroidRuntime(22438):    at android.os.Looper.loop(Looper.java:123)
11-28 14:28:44.435: E/AndroidRuntime(22438):    at android.app.ActivityThread.main(ActivityThread.java:3691)
11-28 14:28:44.435: E/AndroidRuntime(22438):    at java.lang.reflect.Method.invokeNative(Native Method)
11-28 14:28:44.435: E/AndroidRuntime(22438):    at java.lang.reflect.Method.invoke(Method.java:507)
11-28 14:28:44.435: E/AndroidRuntime(22438):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:847)
11-28 14:28:44.435: E/AndroidRuntime(22438):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605)
11-28 14:28:44.435: E/AndroidRuntime(22438):    at dalvik.system.NativeStart.main(Native Method)
hey est-ce qui fonctionne pour u l'enregistrement des deux côtés ?
quel a été le ACTION_FILTER pour le récepteur de radiodiffusion dans le manifeste?

OriginalL'auteur Piotr Sobecki | 2011-11-28