Android 去电状态判断 录音

2019-04-13 14:50发布

产品提了一个人让人头大的项目,让人很郁闷,让判断用户打电话是否打通,这让我好生郁闷,我记得Android里面好像有对来电有状态的判断,而对去电没有吧。还是说我孤陋寡闻了,赶紧上网找资料,找了好半天,终于找到了一些相关的资料。好了,废话不多说,直接来看看怎么实现的吧。
首先用广播监听,(这里补充一点,不会广播的孩子,可以看看广播的相关资料,这里不多说),具体的代码实现如下:
PhonecallReceiver.java文件 public abstract class PhonecallReceiver extends BroadcastReceiver { //The receiver will be recreated whenever android feels like it. We need a static variable to remember data between instantiations private static int lastState = TelephonyManager.CALL_STATE_IDLE; private static Date callStartTime; private static boolean isIncoming; private static String savedNumber; //because the passed incoming is only valid in ringing @Override public void onReceive(Context context, Intent intent) { //We listen to two intents. The new outgoing call only tells us of an outgoing call. We use it to get the number. if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")) { savedNumber = intent.getExtras().getString("android.intent.extra.PHONE_NUMBER"); Log.e("TAG","===savedNumber==="+savedNumber); } else{ String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE); String number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER); int state = 0; if(stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)){ state = TelephonyManager.CALL_STATE_IDLE; } else if(stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)){ state = TelephonyManager.CALL_STATE_OFFHOOK; } else if(stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)){ state = TelephonyManager.CALL_STATE_RINGING; } onCallStateChanged(context, state, number); } } //Derived classes should override these to respond to specific events of interest protected abstract void onIncomingCallReceived(Context ctx, String number, Date start); protected abstract void onIncomingCallAnswered(Context ctx, String number, Date start); protected abstract void onIncomingCallEnded(Context ctx, String number, Date start, Date end); protected abstract void onOutgoingCallStarted(Context ctx, String number, Date start); protected abstract void onOutgoingCallEnded(Context ctx, String number, Date start, Date end); protected abstract void onMissedCall(Context ctx, String number, Date start); //Deals with actual events //Incoming call- goes from IDLE to RINGING when it rings, to OFFHOOK when it's answered, to IDLE when its hung up //Outgoing call- goes from IDLE to OFFHOOK when it dials out, to IDLE when hung up public void onCallStateChanged(Context context, int state, String number) { if(lastState == state){ //No change, debounce extras return; } switch (state) { case TelephonyManager.CALL_STATE_RINGING: isIncoming = true; callStartTime = new Date(); savedNumber = number; onIncomingCallReceived(context, number, callStartTime); break; case TelephonyManager.CALL_STATE_OFFHOOK: //Transition of ringing->offhook are pickups of incoming calls. Nothing done on them if(lastState != TelephonyManager.CALL_STATE_RINGING){ isIncoming = false; callStartTime = new Date(); onOutgoingCallStarted(context, savedNumber, callStartTime); } else { isIncoming = true; callStartTime = new Date(); onIncomingCallAnswered(context, savedNumber, callStartTime); } break; case TelephonyManager.CALL_STATE_IDLE: //Went to idle- this is the end of a call. What type depends on previous state(s) if(lastState == TelephonyManager.CALL_STATE_RINGING){ //Ring but no pickup- a miss onMissedCall(context, savedNumber, callStartTime); } else if(isIncoming){ onIncomingCallEnded(context, savedNumber, callStartTime, new Date()); } else{ onOutgoingCallEnded(context, savedNumber, callStartTime, new Date()); } break; } lastState = state; } } 具体的的在开发中直接继承这个抽象类就OK,看看下面的具体实现。
CallReceiver.java 文件 public class CallReceiver extends PhonecallReceiver { @Override protected void onIncomingCallReceived(Context ctx, String number, Date start) { } @Override protected void onIncomingCallAnswered(Context ctx, String number, Date start) { } @Override protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end) { } @Override protected void onOutgoingCallStarted(Context ctx, String number, Date start) { // 去电的时候调用这个方法,,打通的时候调用,具体的根据自己的项目需求来实现 } @Override protected void onOutgoingCallEnded(Context ctx, String number, Date start, Date end) { // 这里处理,挂断的相关操作, } @Override protected void onMissedCall(Context ctx, String number, Date start) { } } 如果,有的同学需要对,拨打电话的状态监听录音,可以根据自己的需求来实现录音功能,下面给出录音的代码。 public class CustomRecorder { private String phoneNumber; private MediaRecorder mrecorder; private boolean started = false; //录音机是否已经启动 private boolean isCommingNumber = false;//是否是来电 private String TAG = "Recorder"; public CustomRecorder(String phoneNumber) { this.setPhoneNumber(phoneNumber); } public CustomRecorder() { } public void start() { started = true; mrecorder = new MediaRecorder(); File recordPath = new File( Environment.getExternalStorageDirectory() , "/CustomRecorder"); if (!recordPath.exists()) { recordPath.mkdirs(); Log.d("recorder", "创建目录"); } String callDir = "呼出"; if (isCommingNumber) { callDir = "呼入"; } String fileName = callDir + "-" + phoneNumber + "-" + new SimpleDateFormat("yy-MM-dd_HH-mm-ss") .format(new Date(System.currentTimeMillis())) + ".mp3";//实际是3gp File recordName = new File(recordPath, fileName); try { recordName.createNewFile(); Log.d("recorder", "创建文件" + recordName.getName()); } catch (IOException e) { e.printStackTrace(); } mrecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT); mrecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT); mrecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); mrecorder.setOutputFile(recordName.getAbsolutePath()); try { mrecorder.prepare(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } mrecorder.start(); started = true; Log.d(TAG , "录音开始"); } public void stop() { try { if (mrecorder!=null) { mrecorder.stop(); mrecorder.release(); mrecorder = null; } started = false; } catch (IllegalStateException e) { e.printStackTrace(); } Log.d(TAG , "录音结束"); } public void pause() { } public String getPhoneNumber() { return phoneNumber; } public void setPhoneNumber(String phoneNumber) { this.phoneNumber = phoneNumber; } public boolean isStarted() { return started; } public void setStarted(boolean hasStarted) { this.started = hasStarted; } public boolean isCommingNumber() { return isCommingNumber; } public void setIsCommingNumber(boolean isCommingNumber) { this.isCommingNumber = isCommingNumber; } } 下面主要的是权限问题,直接在AndroidManifest.xml文件中加入相关的代码。 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/> <uses-permission android:name="android.permission.RECORD_AUDIO"/> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 前面说了一大堆东西,主要的还没有完成,是什么呢???
当然是广播的注册呀,主要的注册都没有,怎么监听啊,对吧,看下面吧。 <receiver android:name=".receiver.CallReceiver" > <intent-filter> <action android:name="android.intent.action.PHONE_STATE" /> intent-filter> <intent-filter> <action android:name="android.intent.action.NEW_OUTGOING_CALL" /> intent-filter> receiver> 最后,需要在activity里面做相关的打电话操作,算了,也就这么几行代码,也弄出来吧,方便后面学习的人参考。 // 检查是否获得了权限(Android6.0运行时权限) if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) { // 没有获得授权,申请授权 if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.CALL_PHONE)) { Toast.makeText(MainActivity.this, "请授权!", Toast.LENGTH_LONG).show(); // 帮跳转到该应用的设置界面,让用户手动授权 Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.fromParts("package", getPackageName(), null); intent.setData(uri); startActivity(intent); } else { // 不需要解释为何需要该权限,直接请求授权 ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CALL_PHONE}, MY_PERMISSIONS_REQUEST_CALL_PHONE); } } else { CallPhone(); Intent intent = new Intent(); intent.setAction(Intent.ACTION_CALL); intent.setData(Uri.parse("tel:" + "你的电话号码")); startActivity(intent); } 好了,到此就算结束了,希望能帮到各位啊,
欢迎大家发表意见。