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

在此过程中,犯了一个很大的错误。对电话状态还不熟悉就开始编程,使得我就算编写正确也出现各种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. 单链表的python实现

    首先说下线性表,线性表是一种最基本,最简单的数据结构,通俗点讲就是一维的存储数据的结构. 线性表分为顺序表和链接表: 顺序表示指的是用一组地址连续的存储单元依次存储线性表的数据元素,称为线性表的顺序存 ...

  2. 阿里云 Windows Server 2012 r2 部署asp.net mvc网站 平坑之旅

    做了多年的Web开发工作,网站部署也不在话下,可每次部署却并不是十分顺利,将本次在阿里云服务器上部署asp.net mvc网站遇到的问题记录如下. 平台是阿里云ECS,操作系统是 Windows Se ...

  3. rabbitMQ教程(五)rabbitmq 指令 以及解决web管理界面无法使用guest用户登录

    安装最新版本的rabbitmq(3.3.1),并启用management plugin后,使用默认的账号guest登陆管理控制台,却提示登陆失败. 翻看官方的release文档后,得知由于账号gues ...

  4. 如何用CSS3画出一个立体魔方?

    前言 最近在写<动画点点系列>文章,上一期分享了< 手把手教你如何绘制一辆会跑车 >,本期给大家带来是结合CSS3画出来的一个立体3d魔方,结合了js让你随心所欲想怎么转,就怎 ...

  5. [iOS]一行代码集成空白页面占位图(基于runtime+MJRefresh思想)

    2018年01月03日阅读 2472   [iOS]一行代码集成空白页面占位图(基于runtime+MJRefresh思想) LYEmptyView 此框架是本人在5,6个月前,公司启动新项目的时候, ...

  6. Redis使用和部分源码剖析以及Django缓存和redis的关系

    0.特点: a.持久化 b.单进程.单线程 c.5大数据类型    d.用于操作内存的软件.    e.虽然是缓存数据库但是可以做持久化的工作 MySQL是一个软件,帮助开发者对一台机器的硬盘进行操作 ...

  7. Go To Oracle

    1.下载mingw   (gcc 编译)---win32 2.下载OCI最新版,存放于C:\instantclient_12_1   ---win32 3.下载OCI SDK最新版,存放于C:\ins ...

  8. [转帖]利用hydra(九头蛇)暴力破解内网windows登录密码

    利用hydra(九头蛇)暴力破解内网windows登录密码 https://blog.csdn.net/weixin_37361758/article/details/77939070 尝试了下 能够 ...

  9. Unit 1.前端基础之html

    一.什么是html 定义:全称是超文本标记语言(HyperText Markup Language),它是一种用于创建网页的标记语言.标记语言是一种将文本(Text)以及文本相关的其他信息结合起来,展 ...

  10. JS --- 如何获取一个对象的类型

    可以清楚的看到  拿到数字 字符串 对象 函数 数组 通过.slice(8,-1) 可以拿到类型的名称 ,可以做你想要的操作 Object.prototype.toString.call(222) & ...