Call recording/processing service! - Android

Hallo,

Im arbeiten an einer Lösung für Android, das für die Aufnahme Anrufe (sowohl aus-und eingehende) und Weiterverarbeitung der aufgezeichneten Daten (an das Ende meine Bewerbung, keine audio-Datei werden die Daten halten, die auf Telefon-Speicher). Ich habe BroadcastReceiver implementiert mit PhoneStateListener.LISTEN_CALL_STATE, dass eine Aufzeichnung startet service-wenn Staat CALL_STATE_OFFHOOK. Dann in Dienst ich einen neuen thread starten, der versucht, Aufzeichnung einen Anruf, und ein anderer BroadcastReceiver mit PhoneStateListener.LISTEN_CALL_STATE, dass eine Methode aufruft um die Aufnahme zu stoppen wenn das Telefon Status auf TelephonyManager.CALL_STATE_IDLE.

Die audio-Datei, die erstellt wird ist leer.
- Ausnahme wird ausgelöst, wenn der Rekorder.stop () - Methode in meinem Dienst aufgerufen wird. Wo ist ein Fehler? Was könnte ich besser machen?

Ersten (eigenständigen) 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;
    }
}

Berechtigungen:

<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" />

Ausnahme Ausgabe:

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, es funktioniert für u-Aufnahme beide Seiten ?
  • was war das ACTION_FILTER für die broadcast-receiver im manifest?
Schreibe einen Kommentar