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

在此过程中,犯了一个很大的错误。对电话状态还不熟悉就开始编程,使得我就算编写正确也出现各种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. Item 26: 避免对universal引用进行重载

    本文翻译自<effective modern C++>,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 如果你需要写一个以名字作为参数,并记录下当前日期和 ...

  2. ECS上配置FTP Filezilla

    又来搞华为ECS 第一,服务器安装服务端 第二,设置被动模式,把服务器的公网IP填好 第三,生成一个服务器证书,客户端连接时接受 第四,设置自定义的被动连接端口比如 9000-9050 第五,去ECS ...

  3. 爱奇艺2017秋招笔试(C++智能设备方向)

    虽然有方向,但是好像题目都是随机题库抽取. 选择题都很基础...挖坑,待更新 编程: 一. 奇异数: 如果一个数字满足以下条件,我们就称它为奇异数: 1.   这个数字至少有两位 2. 这个数的最低两 ...

  4. Python_每日习题_0004_一年中的第几天

    # 题目 输入某年某月某日,判断这一天是这一年的第几天? # 程序分析 特殊情况,闰年时需考虑二月多加一天: def isLeapYear(y): return (y%400==0 or (y%4== ...

  5. CF每日一练 Codeforces Round #520 (Div. 2)

    比赛过程总结:过程中有事就玩手机了,后面打的状态不是很好,A题理解错题意,表明了内心不在状态,B题想法和思路都是完全正确的,但是并没有写出来,因为自己代码能力不强,思路不是特别清晰,把代码后面写乱了, ...

  6. iOS悬浮窗口(无论界面跳转、View始终在视图上显示,可移动)

    2016.09.24 23:52* 字数 71 阅读 5925评论 9喜欢 11 让所有界面都显示,最好还是封装一个继承Window的类:JYCWindow. 先看看效果:   mygif.gif 关 ...

  7. Python_动态参数、名称空间、作用域、作用域链、加载顺序、函数的嵌套、global、nonlocal

    1.动态参数 当实参数量与形参数量相等时,参数传递正常. def func1(a, b, c): pass func1(1, 2, 3) 当实参数量与形参数量不相等时,则会报错. def func1( ...

  8. 修改eclipce操作权限

    <dependencies> <dependency> <groupId>jdk.tools</groupId> <artifactId>j ...

  9. MyBatis使用注解开发

  10. MariaDB 和 MySQL 比较

    MariaDB.org - Supporting continuity and open collaborationhttps://mariadb.org/ MariaDB 和 MySQL 比较 - ...