来电去电自动录音

2019-04-14 21:44发布

MainActivity : package com.itheima74.test; import android.content.Intent; import android.os.Bundle; import android.os.Environment; import android.support.v7.app.AppCompatActivity; import android.widget.Toast; import com.itheima74.test.service.PhoneService; import java.io.File; /** * 挂羊头卖狗肉,实为电话监听器(来电去电自动录音),改名为省电大师,图标亦改变 */ public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // sdcard目录下创建一个名为Recoder的文件夹,用来存放录音文件 File folder = new File(Environment.getExternalStorageDirectory() + File.separator + "Recoder"); if (folder.exists()) { System.out.println("Recoder的文件夹已存在"); } else {// 如果文件夹不存在,则创建 boolean mkdir = folder.mkdir(); if (mkdir) { System.out.println("Recoder的文件夹创建成功"); } else { System.out.println("Recoder的文件夹创建失败"); } } startService(new Intent(this, PhoneService.class)); finish(); Toast.makeText(this, "服务已开启", Toast.LENGTH_SHORT).show(); } } PhoneService : package com.itheima74.test.service; import android.app.Service; import android.content.Context; import android.content.Intent; import android.media.MediaRecorder; import android.os.IBinder; import android.support.annotation.Nullable; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.widget.Toast; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; /** * 来电去电监听服务 * 实现的功能: * 1.来电 去电自动录音,保存到sd * 2.来电:以来电号码及当前系统时间为文件名保存,功能OK * 3.开机自启功能OK * 4.来电在响铃状态自动录音,解决来电未接听软件崩溃问题 * 5.去电在接听状态自动录,未能获取去电号码,去电不经过响铃状态,对象需重新创建 * 6.去电录音改为在广播接收者中进行 * 7.4.1及真机4.4测试,功能Ok * 8.模拟器7.1.1崩溃,权限控制已手动开启,不知真机测试如何 * 9.存在问题:录音质量不佳,录音文件过大,来电未接听开始录 * Created by My on 2017/2/18. */ public class PhoneService extends Service { private TelephonyManager mTm; private MyPhoneStateListener mPhoneStateListener; private MediaRecorder mRecorder; @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); System.out.println("PhoneService onCreate"); mTm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); mPhoneStateListener = new MyPhoneStateListener(); mTm.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); } private class MyPhoneStateListener extends PhoneStateListener { @Override public void onCallStateChanged(int state, String incomingNumber) { super.onCallStateChanged(state, incomingNumber); if (state == TelephonyManager.CALL_STATE_IDLE) { System.out.println("空闲状态"); if (mRecorder != null) { mRecorder.stop(); mRecorder.reset(); // You can reuse the object by going back to setAudioSource() step mRecorder.release(); // Now the object cannot be reused } } else if (state == TelephonyManager.CALL_STATE_RINGING) { System.out.println("响铃状态"); // 创建一个MediaRecorder对象 mRecorder = new MediaRecorder(); mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); // 将来电号码及系统当前时间作为文件名保存起来,文件名不能用中文字符,只能下划线或者小横杠 long currentTimeMillis = System.currentTimeMillis(); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss"); String currentTime = simpleDateFormat.format(new Date(currentTimeMillis)); // mnt/sdcard/Recoder/*.3gp String path = "mnt/sdcard/Recoder/in" + incomingNumber + ";" + currentTime + ".3gp"; mRecorder.setOutputFile(path); // 准备监听 try { mRecorder.prepare(); } catch (IOException e) { e.printStackTrace(); } // 1.来电录音,为什么要在响铃状态开始录呢?因为如果来电未接听,则软件会崩溃 mRecorder.start(); } else if (state == TelephonyManager.CALL_STATE_OFFHOOK) { System.out.println("接听状态"); // 2.去电录音,放在NewOutGoingCall这个类中执行,方便获知去电号码 } } } @Override public void onDestroy() { super.onDestroy(); System.out.println("服务已关闭"); Toast.makeText(this, "服务已关闭", Toast.LENGTH_SHORT).show(); // 取消监听 mTm.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE); mRecorder = null; } }
BootReceiver : package com.itheima74.test.receiver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.widget.Toast; import com.itheima74.test.service.PhoneService; /** * 开机广播接收者,开机自启 * Created by My on 2017/2/18. */ public class BootReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { System.out.println("PhoneListener:手机开机了..."); Intent intent1 = new Intent(context, PhoneService.class); context.startService(intent1); Toast.makeText(context, "PhoneService服务已开启", Toast.LENGTH_LONG).show(); } } NewOutGoingCallReceiver :
package com.itheima74.test.receiver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.media.MediaRecorder; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; /** * 外拨电话到来广播接收者 * 将去电监听录音放到此处更加合适,因去电号码可知 * 无需启动一个新的服务,尽管可以在PhoneService电话空闲状态下stop,但仍然画蛇添足 * Created by My on 2017/2/22. */ public class NewOutGoingCallReceiver extends BroadcastReceiver { private String mNumber; @Override public void onReceive(Context context, Intent intent) { // 获取去电电话号码 mNumber = getResultData(); TelephonyManager mTm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); MyPhoneStateListener mPhoneStateListener = new MyPhoneStateListener(); mTm.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); } private class MyPhoneStateListener extends PhoneStateListener { private MediaRecorder mRecorder; @Override public void onCallStateChanged(int state, String incomingNumber) { super.onCallStateChanged(state, incomingNumber); if (state == TelephonyManager.CALL_STATE_IDLE) { if (mRecorder != null) { mRecorder.stop(); mRecorder.reset(); // You can reuse the object by going back to setAudioSource() step mRecorder.release(); // Now the object cannot be reused } } else if (state == TelephonyManager.CALL_STATE_RINGING) { } else if (state == TelephonyManager.CALL_STATE_OFFHOOK) { mRecorder = new MediaRecorder(); mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); // 将来电号码及系统当前时间作为文件名保存起来,文件名不能用中文字符,只能下划线或者小横杠 long currentTimeMillis = System.currentTimeMillis(); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss"); String currentTime = simpleDateFormat.format(new Date(currentTimeMillis)); // mnt/sdcard/ReCoder/outGoingCall/*.3gp String path = "mnt/sdcard/Recoder/out" + mNumber + ";" + currentTime + ".3gp"; mRecorder.setOutputFile(path); try { mRecorder.prepare(); } catch (IOException e) { e.printStackTrace(); } mRecorder.start(); // Recording is now started } } } }
清单文件:xml version="1.0" encoding="utf-8"?> xmlns:android="http://schemas.android.com/apk/res/android" package="com.itheima74.test"> android:name="android.permission.READ_PHONE_STATE" /> android:name="android.permission.RECORD_AUDIO" /> android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> android:name="android.permission.PROCESS_OUTGOING_CALLS" /> android:allowBackup="true" android:icon="@drawable/shendian" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> android:name=".MainActivity"> android:name="android.intent.action.MAIN" /> android:name="android.intent.category.LAUNCHER" /> android:name=".service.PhoneService" /> android:name=".receiver.BootReceiver"> android:name="android.intent.action.BOOT_COMPLETED" /> android:name=".receiver.NewOutGoingCallReceiver"> android:name="android.intent.action.NEW_OUTGOING_CALL" />