Приложение Call Recorder Работает на устройствах Android ниже 7.0.0 ... но не работает с версией Android 8.0.0 Oreo - PullRequest
0 голосов
/ 11 октября 2018

Устройство записи вызовов моего приложения работает на устройствах с Android ниже 7.0.0, но не работает с Android 8.0.0 Oreo.Он записывает все звонки, но в Android 8.0.0 Oreo не показывает уведомлений и не записывает никаких звонков.Как использовать службу переднего плана в Android?

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import com.callrecorder.R;
import com.callrecorder.helper.SecurePreferences;

import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.net.Uri;
import android.os.Environment;
import android.os.IBinder;
import android.os.PowerManager;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

public class CallRecorderService extends Service {
    public static File amr;
    public static final String ACTION = "com.callrecorder.CALL_RECORD";
    public static final String STATE = "STATE";
    public static final String START = "START";
    public static final String STORAGE = "STORAGE";
    public static final String INCOMING = "INCOMING";
    public static final String OUTGOING = "OUTGOING";
    public static final String BEGIN = "BEGIN";
    public static final String END = "END";

    protected static final String TAG = CallRecorderService.class.getName();
    protected static final boolean DEBUG = false;
    private static final int RECORDING_NOTIFICATION_ID = 1;

    private static final String AMR_DIR = "/AutoCallRecording/";
    private static final String IDLE = "";
    private static final String INCOMING_CALL_SUFFIX = "_inCall";
    private static final String OUTGOING_CALL_SUFFIX = "_outCall";

    private Context cntx;
    private volatile String fileNamePrefix = IDLE;
    private volatile MediaRecorder recorder;
    private volatile PowerManager.WakeLock wakeLock;
    private volatile boolean isMounted = false;
    private volatile boolean isInRecording = false;

    @Override
    public IBinder onBind(Intent i) {
        return null;
    }

    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();
        this.cntx = getApplicationContext();
        this.prepareAmrDir();
        log("service create");
    }

    @Override
    public void onDestroy() {
        log("service destory");
        this.stopRecording();
        this.cntx = null;
        super.onDestroy();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (null == intent || !ACTION.equals(intent.getAction())) {
            return super.onStartCommand(intent, flags, startId);
        }
        String state = intent.getStringExtra(STATE);
        String phoneNo = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
        log("state: " + state + " phoneNo: " + phoneNo);
        if (OUTGOING.equals(state)) {
            fileNamePrefix = "(" + phoneNo + ")" + OUTGOING_CALL_SUFFIX;
        } else if (INCOMING.equals(state)) {
            fileNamePrefix = "(" + phoneNo + ")" + INCOMING_CALL_SUFFIX;
        } else if (BEGIN.equals(state)) {
            if (SecurePreferences.getBooleanPreference(this, Constants.PREF_RECORD_CALLS)) {
                startRecording();
            }
        } else if (END.equals(state)) {
            stopRecording();
        } else if (STORAGE.equals(state)) {
            String mountState = Environment.getExternalStorageState();
            if (Environment.MEDIA_MOUNTED.equals(mountState)) {
                prepareAmrDir();
            } else {
                isMounted = false;
            }
            if (!isInRecording) {
                stopSelf();
            }
        }
        return START_STICKY;
    }

    public Context getContext() {
        return cntx;
    }

    private void stopRecording() {
        updateNotification(false);
        if (isInRecording) {
            isInRecording = false;
            try {
                recorder.stop();
                recorder.release();
                recorder = null;
            } catch (Exception e) {
                // TODO: handle exception
                e.printStackTrace();
            }

            releaseWakeLock();

//          MediaPlayer mp = MediaPlayer.create(getApplicationContext(), Uri.parse(amr.getAbsolutePath()));
//          int duration = 0;
//          if (mp != null) {
//              duration = mp.getDuration();
//          }

//          if (duration > 2000) {

                if (SecurePreferences.getBooleanPreference(this, Constants.PREF_SAVE_RECORDING)) {

                    Intent intent = new Intent(CallRecorderService.this, AutoRunReceiver.class);
                    String ACTION_SHOW_ALERT_DIALOG = "com.callrecorder.SHOW_ALERT_DIALOG";
                    intent.setAction(ACTION_SHOW_ALERT_DIALOG);
                    intent.putExtra("absolutepath", amr.getAbsolutePath());
                    sendBroadcast(intent);
                }
//          } else {
//              File file = new File(amr.getAbsolutePath());
//              boolean deleted = file.delete();
//          }

            stopSelf();
            log("call recording stopped");

        }
    }

    private void updateNotification(Boolean status) {

        String ns = Context.NOTIFICATION_SERVICE;
        NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);

        if (status) {

            CharSequence contentTitle = "CallRecorder Status";
            CharSequence contentText = "Recording call from channel...";
            Intent notificationIntent = new Intent(this, CallRecorderService.class);

            PendingIntent alarmIntent = PendingIntent.getActivity(this, 0, notificationIntent,
                    PendingIntent.FLAG_UPDATE_CURRENT);

            NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
                    .setSmallIcon(R.drawable.ic_launcher).setContentTitle(contentTitle)
                    .setStyle(new NotificationCompat.BigTextStyle().bigText(contentText)).setAutoCancel(true)
                    .setContentText(contentText);

            mBuilder.setContentIntent(alarmIntent);
            mNotificationManager.notify(RECORDING_NOTIFICATION_ID, mBuilder.build());
        } else {
            mNotificationManager.cancel(RECORDING_NOTIFICATION_ID);
        }
    }

    private String getDateTimeString() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd'_'HHmmss");
        Date now = new Date();
        return sdf.format(now);
    }

    private String getMonthString() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
        Date now = new Date();
        return sdf.format(now);
    }

    private String getDateString() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        Date now = new Date();
        return sdf.format(now);
    }

    private String getTimeString() {
        SimpleDateFormat sdf = new SimpleDateFormat("HHmmss");
        Date now = new Date();
        return sdf.format(now);
    }

    private void startRecording() {
        if (SecurePreferences.getBooleanPreference(this, Constants.PREF_NOTIFICATION_ENABLE)) {
            updateNotification(true);
        } else {
            updateNotification(false);
        }
        if (!isMounted) {
            stopRecording();
            updateNotification(false);
            return;
        }
        try {

            int format = SecurePreferences.getIntegerPreference(this, Constants.PREF_AUDIO_FORMAT);

            String exten = format == 1 ? ".3gpp" : format == 2 ? ".mpg" : ".amr";
            amr = new File(Constants.StoragePath + getDateTimeString() + "_" + fileNamePrefix + exten);
            log("Prepare recording in " + amr.getAbsolutePath());
            recorder = new MediaRecorder();
            recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION);
            recorder.setOutputFormat(format);
            recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
            recorder.setOutputFile(amr.getAbsolutePath());
            recorder.prepare();
            recorder.start();
            isInRecording = true;
            acquireWakeLock();
            log("Recording in " + amr.getAbsolutePath());
        } catch (Exception e) {
            Log.w(TAG, e);
        }
    }

    private void prepareAmrDir() {
        isMounted = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
        if (!isMounted)
            return;
        File amrRoot = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + AMR_DIR);
        if (!amrRoot.isDirectory())
            amrRoot.mkdir();
    }

    private void log(String info) {
        if (DEBUG && isMounted) {
            File log = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + AMR_DIR + "log_"
                    + getMonthString() + ".txt");
            try {
                BufferedWriter out = new BufferedWriter(new FileWriter(log, true));
                try {
                    synchronized (out) {
                        out.write(getDateString() + getTimeString());
                        out.write(" ");
                        out.write(info);
                        out.newLine();
                    }
                } finally {
                    out.close();
                }
            } catch (IOException e) {
                Log.w(TAG, e);
            }
        }
    }

    private void acquireWakeLock() {
        if (wakeLock == null) {
            log("Acquiring wake lock");
            PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
            wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, this.getClass().getCanonicalName());
            wakeLock.acquire();
        }

    }

    private void releaseWakeLock() {
        if (wakeLock != null && wakeLock.isHeld()) {
            wakeLock.release();
            wakeLock = null;
            log("Wake lock released");
        }

    }
}

package com.callrecorder;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.util.Log;

public class AutoRunReceiver extends BroadcastReceiver {
    String ACTION_SHOW_ALERT_DIALOG = "com.callrecorder.SHOW_ALERT_DIALOG";

    @Override
    public void onReceive(Context context, Intent intent) {
        if (null == intent)
            return;
        Intent i = new Intent(CallRecorderService.ACTION);
        i.setPackage("com.callrecorder");
        if (intent.getAction().equals(ACTION_SHOW_ALERT_DIALOG)) {
            Intent intentDialog = new Intent(context, DialogClass.class);
            String absolutepath = intent.getStringExtra("absolutepath");
            intentDialog.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intentDialog.putExtra("absolutepath", absolutepath);
            context.startActivity(intentDialog);
        }
        if (Intent.ACTION_NEW_OUTGOING_CALL.equals(intent.getAction())) {
            i.putExtra(CallRecorderService.STATE, CallRecorderService.OUTGOING);
            i.putExtra(Intent.EXTRA_PHONE_NUMBER,
                    intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER));
        } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(intent
                .getAction())) {
            String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
            if (TelephonyManager.EXTRA_STATE_RINGING.equals(state)) {
                i.putExtra(CallRecorderService.STATE,
                        CallRecorderService.INCOMING);
                i.putExtra(Intent.EXTRA_PHONE_NUMBER, intent
                        .getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER));
            } else if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(state)) {
                i.putExtra(CallRecorderService.STATE, CallRecorderService.BEGIN);
            } else if (TelephonyManager.EXTRA_STATE_IDLE.equals(state)) {
                i.putExtra(CallRecorderService.STATE, CallRecorderService.END);
            }
        } else if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
            i.putExtra(CallRecorderService.STATE, CallRecorderService.START);
        } else if (intent.getAction().equals(Intent.ACTION_MEDIA_MOUNTED)
                || intent.getAction().equals(Intent.ACTION_MEDIA_REMOVED)) {
            i.putExtra(CallRecorderService.STATE, CallRecorderService.STORAGE);
        } else {
            return;
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            context.startForegroundService(new Intent(context, CallRecorderService.class));
        } else {
            context.startService(new Intent(context, CallRecorderService.class));
        }


        Log.d(CallRecorderService.TAG,
                "AutoRunReceiver startService "
                        + i.getStringExtra(CallRecorderService.STATE) + ":"
                        + i.getStringExtra(Intent.EXTRA_PHONE_NUMBER));
    }
}

android:minSdkVersion="21"
    android:targetSdkVersion="26" />


<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<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" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
...