也许有时你会有这样一个需求:通电话时有一个重要的事需要记下来或者和一个陌生人特别是大骗子通话时,这是就想如果能把通话录下来就方便多了。(这才是我写这个代码的目的!!!)

在此过程中,犯了一个很大的错误。对电话状态还不熟悉就开始编程,使得我就算编写正确也出现各种bug。

先将代码列出来,供大家参考,然后解释错误和相关知识。

activity_main.xml:

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.lgqchinese.homework3.MainActivity" > <Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="开启服务"
android:id="@+id/btn_startService"
/> <Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="关闭服务"
android:id="@+id/btn_stopService"
/> </LinearLayout>

MainAvtivity.java:

/**
* 在这里启动服务
*/ import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button; public class MainActivity extends Activity implements OnClickListener{ @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); Button btn_startService = (Button) findViewById(R.id.btn_startService);
Button btn_stopService = (Button) findViewById(R.id.btn_stopService); //监听按钮点击
btn_startService.setOnClickListener(this);
btn_stopService.setOnClickListener(this);
} @Override
public void onClick(View v) { Intent service = new Intent(getApplicationContext(), MyService.class); switch (v.getId()) {
case R.id.btn_startService:
startService(service); // bindService(service, conn, flags 为了调用服务里面方法
break;
case R.id.btn_stopService:
stopService(service);
break; } } }

MyServier.java:

package com.lgqchinese.homework3;

import android.app.Service;
import android.content.Intent;
import android.media.MediaRecorder;
import android.os.IBinder;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager; import java.io.IOException; public class MyService extends Service {
private MediaRecorder recorder;
public MyService() {
} @Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return null;
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
System.out.println("onCreate"); // 监听电话状态
TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE); tm.listen(new myListen(), PhoneStateListener.LISTEN_CALL_STATE); super.onCreate();
} public class myListen extends PhoneStateListener { @Override
public void onCallStateChanged(int state, String incomingNumber) {
// TODO Auto-generated method stub
/**
* Callback invoked when device call state changes.
*
* @see TelephonyManager#CALL_STATE_IDLE
* @see TelephonyManager#CALL_STATE_RINGING
* @see TelephonyManager#CALL_STATE_OFFHOOK
*/
switch (state) {
case TelephonyManager.CALL_STATE_IDLE: // 空闲状态
System.out.println("CALL_STATE_IDLE: //空闲状态"); if (recorder != null) {
recorder.stop();
recorder.reset(); // You can reuse the object by going back to// setAudioSource() step
recorder.release(); // Now the object cannot be reused } break;
case TelephonyManager.CALL_STATE_RINGING: // 响铃状态
System.out.println("CALL_STATE_RINGING: //响铃状态"); recorder = new MediaRecorder();
//音频来源
System.out.println("声音来源");
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
//音频的输出格式
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); //3gp
System.out.println("输出格式");
//设置音频编码格式
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
System.out.println("编码格式");
//音频输出文件地址
recorder.setOutputFile("/mnt/sdcard/luyin.3gp");
System.out.println("文件路径");
//准备录音 try {
recorder.prepare();
System.out.println("正在准备");
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
System.out.println("IllegalStateException异常");
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("IOException异常");
} break;
case TelephonyManager.CALL_STATE_OFFHOOK: // 接听状态
System.out.println("CALL_STATE_OFFHOOK: //接听状态");
//开始录音
recorder.start(); // Recording is now started
break; } super.onCallStateChanged(state, incomingNumber);
}
} @Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
System.out.println("onStartCommand");
return super.onStartCommand(intent, flags, startId);
} @Override
public void onDestroy() {
// TODO Auto-generated method stub
System.out.println("onDestroy");
super.onDestroy();
}
}

Ok,代码完成。现在就让我们拔打电话来试试吧。(此时很多读过相关文档的小白一定都在笑话我吧)

咦~~,出现这么个问题:

为啥不行!为啥不行!为啥不行!开始调试:

找到了这个:

即在

//开始录音
recorder.start(); // Recording is now started

出现问题,但里面的system.out也执行了呀

然后你还会觉得是start()的问题吗?——会!

应该会发现在响铃状态里面的语句都没执行。所以在start()前面的一些必备方法并没有执行,导致录音失败。

我把响铃状态里面的语句拿到空闲状态,再拨打电话,成功了。。。。。不是真正的成功,虽然可以录音。

此时,就在此时,我还没有阅读有关状态的知识。

我进入CALL_STATE_RINGING所在类,发现里面全部标红:

然后。。我。。把sdk卸载重装一边——(此时智商已经下线了,明明是Android Studio还没加载完)

Ok。Ok,趁这空吃个晚饭,回来后想到了错误:

经过阅读发现,响铃状态,即CALL_STATE_RINGING并不是打电话的状态,那就是接电话的状态了。

敲了半天,不,敲了一天,原来是接电话。结果如下:

由于没有理解电话状态代码的含义,明明对的代码还在不断的调试。以后要避免这种低级的错误。

下面需要记录下状态码的含义:

电话状态:

状态码所在类是TelephonyManager:

CALL_STATE_IDLE 无任何状态时

CALL_STATE_OFFHOOK 接起电话时

CALL_STATE_RINGING 电话进来时

数据活动状态:

DATA_ACTIVITY_IN 数据连接状态:活动,正在接受数据

DATA_ACTIVITY_OUT 数据连接状态:活动,正在发送数据

DATA_ACTIVITY_INOUT 数据连接状态:活动,正在接受和发送数据

DATA_ACTIVITY_NONE 数据连接状态:活动,但无数据发送和接受

数据连接状态:

DATA_CONNECTED 数据连接状态:已连接

DATA_CONNECTING 数据连接状态:正在连接

DATA_DISCONNECTED 数据连接状态:断开

DATA_SUSPENDED 数据连接状态:暂停

网络类型:

NETWORK_TYPE_CDMA 网络类型为CDMA

NETWORK_TYPE_EDGE 网络类型为EDGE

NETWORK_TYPE_EVDO_0 网络类型为EVDO0

NETWORK_TYPE_EVDO_A 网络类型为EVDOA

NETWORK_TYPE_GPRS 网络类型为GPRS

NETWORK_TYPE_HSDPA 网络类型为HSDPA

NETWORK_TYPE_HSPA 网络类型为HSPA

NETWORK_TYPE_HSUPA 网络类型为HSUPA

NETWORK_TYPE_UMTS 网络类型为UMTS

在中国,联通的3G为UMTS或HSDPA,移动和联通的2G为GPRS或EGDE,电信的2G为CDMA,电信的3G为EVDO

移动终端的类型:

PHONE_TYPE_CDMA 手机制式为CDMA,电信

PHONE_TYPE_GSM 手机制式为GSM,移动和联通

PHONE_TYPE_NONE 手机制式未知

移动终端:

SIM_STATE_ABSENT SIM卡未找到

SIM_STATE_NETWORK_LOCKED SIM卡网络被锁定,需要Network PIN解锁

SIM_STATE_PIN_REQUIRED SIM卡PIN被锁定,需要User PIN解锁

SIM_STATE_PUK_REQUIRED SIM卡PUK被锁定,需要User PUK解锁

SIM_STATE_READY SIM卡可用 * SIM_STATE_UNKNOWN SIM卡未知

打电话的功能以后再写。网上很多一起写了,而且都很好。我写一遍主要也是提高自己的水平。

这就完了,得做点什么。我说过了,这才是我的目的。

新建一个类:StartPhoneReceiver.java用来进行开机自启 ,按一下开启服务多不方便呀

package com.lgqchinese.homework3;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent; public class StartPhoneReceiver extends BroadcastReceiver { @Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
//开启服务 Intent service = new Intent(context, MyService.class); context.startService(service);
}
}

在清单文件里注册一下:

<receiver
android:name=".StartPhoneReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>

那你会想看到这个多余的图标吗,在MainActivity.java中加上两行黄底代码:

 @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
PackageManager p = getPackageManager();
p.setComponentEnabledSetting(getComponentName(), PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
7
………………………………
}

好了,这是我的目的。这次的错误让我明白,一定要把文档的知识理解了在动手,不能像今天这么傻X了

学习Android过程中遇到的问题及解决方法——电话监听的更多相关文章

  1. 学习Android过程中遇到的问题及解决方法——网络请求

    在学习Android的网络连接时遇到崩溃或异常(出现的问题就这两个,但是不稳定)的问题,先上代码,看看哪里错了(答案在文末) activity_main.xml: <?xml version=& ...

  2. 学习Android过程中遇到的问题及解决方法——AS为xutils添加依赖

    在使用xutils时遇到不能添加以来的问题,花了很长时间终于解决,网上添加依赖的方法很多,在此针对个人出现的问题作下笔记. 我本想使用jar包,因为在使用smartImageView时是用的jar包来 ...

  3. 国内不fq安装K8S四: 安装过程中遇到的问题和解决方法

    目录 4 安装过程中遇到的问题和解决方法 4.1 常见问题 4.2 常用的操作命令 4.3 比较好的博客 国内不fq安装K8S一: 安装docker 国内不fq安装K8S二: 安装kubernet 国 ...

  4. 将html代码部署到阿里云服务器,并进行域名解析,以及在部署过程中遇到的问题和解决方法

    本博客主要是说一下,,如何将html代码部署到阿里云服务器,并进行域名解析,以及在部署过程中遇到的问题和解决方法. 1.先在阿里云上购买一台阿里云服务器(ECS云服务器): 2.远程连接上该服务器,在 ...

  5. 学习Android过程中的一些博客或工具收集

    android studio中使用SlidingMenu: 超简单Android Studio导入第三方库(SlidingMenu)教程绝对傻瓜版 android 更新sdk23以后,报错提示Floa ...

  6. 学习Android过程中遇到的未解决问题(个人笔记,细节补充,随时更新)

    201811/13 使用HttpURLConnection对象调用方法又出现IO异常,我又百度个博客搜寻答案,未果.下午试试真机,完美.自己建了服务器tomcat,编写android访问自己tomca ...

  7. 蘑菇街TeamTalk编译连接过程中遇到的问题及解决方法(iOS)

    今天浏览博文的时候,“蘑菇街开源的即时通讯框架,包括iOS.Android.Mac.Windows客户端和后台 Github源码下载地址:https://github.com/mogujie/Team ...

  8. 2016最新cocoapods安装流程,安装过程中遇到的问题及解决方法

    现在的cocoapods与之前比较.有很多不一样的地方.自己试了一试,终于搞定.现在大概纪录一下. 1.首先查看ruby是否是最新版的. ruby是通过rvm安装的所以需要先安装rvm后查看ruby是 ...

  9. caffe安装过程中遇到的问题以及解决方法

    1. 在安装依赖库的时候,遇到: @gxjun-Latitude-E5440:~$ sudo apt-get install libatlas-base-dev 正在读取软件包列表... 完成 正在分 ...

随机推荐

  1. Windows Community Toolkit 4.0 - DataGrid - Part03

    概述 在上面一篇 Windows Community Toolkit 4.0 - DataGrid - Part02 中,我们针对 DataGrid 控件的 Utilities 部分做了详细分享.而在 ...

  2. 448C - Painting Fence(分治)

    题意:给出宽为1高为Ai的木板n条,排成一排,每次上色只能是连续的横或竖并且宽度为1,问最少刷多少次可以使这些木板都上上色 分析:刷的第一步要么是所有的都竖着涂完,要么是先横着把最矮的涂完,如果是第一 ...

  3. Masonry练习详解

    添加约束的方式: 1.通过使用NSLayoutConstraints添加约束到约束数组中,之前必须设置translatesAutoresizingMaskIntoConstraints = NO,即取 ...

  4. 使用Browser请求 和 在cli中运行程序的分析

    在browser中请求后端的一个程序之后,立马将窗口关闭,服务器端的程序是否会挂起或者终止,还是继续执行? 如果是继续执行,那么执行完毕后,结果去了哪里?-->apache的工作流程 使用Bro ...

  5. centos yum install nginx

    nginx newshttp://nginx.org/ nginx news: 2017http://nginx.org/2017.html nginx: Linux packageshttps:// ...

  6. spring aop学习记录

    许多AOP框架,比较常用的是Spring AOP 与AspectJ.这里主要学习的Spring AOP. 关于AOP 日志.事务.安全验证这些通用的.散步在系统各处的需要在实现业务逻辑时关注的事情称为 ...

  7. VS2015 + OPENCV + CUDA 安装流程

    VS2015  https://blog.csdn.net/guxiaonuan/article/details/73775519?locationNum=2&fps=1 OPENCV htt ...

  8. C#复习笔记(5)--C#5:简化的异步编程(异步编程的基础知识)

    异步编程的基础知识 C#5推出的async和await关键字使异步编程从表面上来说变得简单了许多,我们只需要了解不多的知识就可以编写出有效的异步代码. 在介绍async和await之前,先介绍一些基础 ...

  9. java 浅拷贝和深拷贝 对象克隆clone

    分一下几点讨论: 为什么要克隆? 如何实现克隆 浅克隆和深克隆 解决多层克隆问题 总结 一:为什么要克隆? 大家先思考一个问题,为什么需要克隆对象?直接new一个对象不行吗? 答案是:克隆的对象可能包 ...

  10. laravel中如何在模型中自关联?

    https://segmentfault.com/q/1010000007926567 在模型中声明一对多的关系,关联表本身.parent_id对应父记录的id.我在sof中查阅到很多这样的写法: p ...