Friday, 9 October 2020

Call Recording in Android 10 Q

 Call Recording in Android 10 is not working without using Accessibility Service ,So here i define you how it is working.




First you have to add permissions in Menifest.xml file like below.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.dv_callrecording_android10">

<uses-permission android:name="android.permission.RECORD_AUDIO"></uses-permission>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<service
android:name=".MyService"
android:label="@string/app_name"
android:enabled="true"
android:exported="true"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data android:name="android.accessibilityservice" android:resource="@xml/accessibility_service_config" />
</service>

</application>

</manifest>




Then make xml folder under res folder name is accessibility_service_config.xml

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:packageNames="test.demo.com.tests"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFlags="flagRetrieveInteractiveWindows|flagReportViewIds|flagIncludeNotImportantViews"
android:accessibilityFeedbackType="feedbackAllMask"
android:notificationTimeout="100"
android:canRetrieveWindowContent="true"
/>


Then Make MyService.java for Accessibility Service like below , Also define your service in Menifest.xml file

import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.media.AudioDeviceInfo;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Handler;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.widget.FrameLayout;

import java.io.IOException;

import androidx.core.app.NotificationCompat;

import static com.dv_callrecording_android10.MainActivity.fileName;
import static com.dv_callrecording_android10.MainActivity.recorder;


public class MyService extends AccessibilityService {

public static final String LOG_TAG_S = "MyService:";

WindowManager windowManager;

@SuppressLint("RtlHardcoded")
@Override
public void onCreate() {
super.onCreate();

windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);

Log.i("start Myservice","MyService");

startForegroundService();
}

@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
Log.e(LOG_TAG_S, "Event :"+event.getEventType());
}
@Override
public void onInterrupt() {
}
@Override
protected void onServiceConnected() {
System.out.println("onServiceConnected");

//==============================Record Audio while Call received===============//

WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
FrameLayout layout = new FrameLayout(this);

WindowManager.LayoutParams params = new WindowManager.LayoutParams(WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| WindowManager.LayoutParams.FLAG_FULLSCREEN |
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS|
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.TOP;

windowManager.addView(layout, params);
layout.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {

Log.e(LOG_TAG_S, "Window view touched........:");
return true;
}
});

//==============To Record Audio wile Call received=================


AccessibilityServiceInfo info = new AccessibilityServiceInfo();
info.eventTypes = AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED;
info.eventTypes= AccessibilityEvent.TYPES_ALL_MASK;
info.feedbackType = AccessibilityServiceInfo.FEEDBACK_ALL_MASK;
info.notificationTimeout = 100;
info.packageNames = null;
setServiceInfo(info);



try {
startRecordingA();
} catch (Exception e) {
e.printStackTrace();
}



new Handler().postDelayed(new Runnable() {
@Override
public void run() {
// This method will be executed once the timer is over

//stopRecording();
stopRecordingA();
}
}, 30000);

}

private void startRecordingA() {
recorder = new MediaRecorder();
// This must be needed sourcea
recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_RECOGNITION);
recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
recorder.setOutputFile(fileName);
//recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.HE_AAC);
recorder.setAudioEncodingBitRate(48000);
} else {
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
recorder.setAudioEncodingBitRate(64000);
}
recorder.setAudioSamplingRate(16000);

try {
recorder.prepare();
} catch (IOException e) {
Log.e(LOG_TAG_S, "prepare() failed");
}

recorder.start();
}



private void stopRecordingA() {

Log.e(LOG_TAG_S, "stop recording");
recorder.stop();
recorder.release();
recorder = null;
}


public static final String CHANNEL_ID = "MyAccessibilityService";

private void startForegroundService() {
createNotificationChannel();
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)

.setContentTitle("recording Service")
.setContentText("Start")
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentIntent(pendingIntent)
.build();
startForeground(1, notification);

}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel serviceChannel = new NotificationChannel(
CHANNEL_ID,
"Recording Service Channel",
NotificationManager.IMPORTANCE_DEFAULT
);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(serviceChannel);
}
}

}



And then in MainActivity.java like below , 


import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.Toast;

import java.io.IOException;

public class MainActivity extends AppCompatActivity {


public static final String LOG_TAG = "AudioRecordTest";
private static final int REQUEST_RECORD_AUDIO_PERMISSION = 200;
public static String fileName = null;

private RecordButton recordButton = null;
public static MediaRecorder recorder = null;

private PlayButton playButton = null;
public static MediaPlayer player = null;

// Requesting permission to RECORD_AUDIO
private boolean permissionToRecordAccepted = false;
private String [] permissions = {Manifest.permission.RECORD_AUDIO};

Context mContext;
boolean isbbTrue = false;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

fileName = getExternalCacheDir().getAbsolutePath();
fileName += "/dv_recodringaudio.3gp";

ActivityCompat.requestPermissions(MainActivity.this, permissions, REQUEST_RECORD_AUDIO_PERMISSION);

mContext = MainActivity.this;

Intent openSettings = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
LinearLayout ll = new LinearLayout(this);
recordButton = new RecordButton(MainActivity.this);
ll.addView(recordButton,
new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
0));
playButton = new PlayButton(MainActivity.this);
ll.addView(playButton,
new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
0));
setContentView(ll);

}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode){
case REQUEST_RECORD_AUDIO_PERMISSION:
permissionToRecordAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
break;
}
if (!permissionToRecordAccepted ) finish();

}
private void onRecord(boolean start) {
if (start) {
startserviceD();
} else {

}
}

private void onPlay(boolean start) {
if (start) {
startPlaying();
} else {
stopPlaying();
}
}

private void startPlaying() {
player = new MediaPlayer();
try {
player.setDataSource(fileName);
player.prepare();
player.start();
} catch (IOException e) {
Log.e(LOG_TAG, "prepare() failed");
}
}

private void stopPlaying() {
player.release();
player = null;
}


class RecordButton extends androidx.appcompat.widget.AppCompatButton {
boolean mStartRecording = true;

OnClickListener clicker = new OnClickListener() {
public void onClick(View v) {

/* Toast.makeText(mContext,"Click....",Toast.LENGTH_SHORT).show();

try {
isbbTrue = MyService.isAccessibilitySettingsOn(mContext);
} catch (Exception e) {
e.printStackTrace();
}

Toast.makeText(mContext,"Service :"+isbbTrue,Toast.LENGTH_SHORT).show();*/





onRecord(mStartRecording);
if (mStartRecording) {
setText("Stop recording");
} else {
setText("Start recording");
}
mStartRecording = !mStartRecording;
}
};

public RecordButton(Context ctx) {
super(ctx);
setText("Start recording");
setOnClickListener(clicker);
}
}

class PlayButton extends androidx.appcompat.widget.AppCompatButton {
boolean mStartPlaying = true;

OnClickListener clicker = new OnClickListener() {
public void onClick(View v) {
onPlay(mStartPlaying);
if (mStartPlaying) {
setText("Stop playing");
} else {
setText("Start playing");
}
mStartPlaying = !mStartPlaying;
}
};

public PlayButton(Context ctx) {
super(ctx);
setText("Start playing");
setOnClickListener(clicker);
}
}


@Override
public void onStop() {
super.onStop();
}

public void startserviceD(){
// Permission for Manifest.permission.SYSTEM_ALERT_WINDOW in Android M
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Settings.canDrawOverlays(getApplicationContext())) {
Intent openSettings = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
openSettings.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(openSettings);

}
}

// Code to start the Service
startService(new Intent(getApplication(), MyService.class));

Toast.makeText(MainActivity.this,"Enable allow Service from Accessbility,Trye,and 30 Sec Recording will Start....",Toast.LENGTH_SHORT).show();

Toast.makeText(MainActivity.this,"After 30 Sec Play Recording File, you can make Call between it",Toast.LENGTH_SHORT).show();

}
}


And run this app . Audio recording file is found you in your mobile's  Internel Storage/Android/data/your app package name/audio.mp3





This is the call recording in Android 10 Q version with Accessibility Service.

                    Android Call Recording in Android 10 Q

 


2 comments:

Comments

Find Hours Diffrence in Kotlin

  In Kotlin, determining the difference in hours between two timestamps is a common task, especially in scenarios involving time-based calcu...