Устройство записи вызовов моего приложения работает на устройствах с 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" />