[转] How to detect incoming calls in an Android

原文地址:[url]https://stackoverflow.com/a/15564021[/url]

实测可用。
测试手机:
MeiZu MX4 Android 5.1
HuaWei Mate 8 Android 7.0

-----------------------------------------------------------
Here's what I use to do this:

AndroidManifest:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>

<!--This part is inside the application-->
<receiver android:name=".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>

My base reusable call detector
package com.gabesechan.android.reusable.receivers;
import java.util.Date;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;

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");
}
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;
}
}

Then to use it, simply derive a class from it and implement a few easy functions, whichever call types you care about:

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)
{
//
}

}

In addition you can see a writeup I did on why the code is like it is on my blog. Gist link: [url]https://gist.github.com/ftvs/e61ccb039f511eb288ee[/url]

EDIT: Updated to simpler code, as I've reworked the class for my own use
在Python中检测CT图像中的木材缺陷通常涉及到图像处理和机器学习相结合的方法。首先,你可以使用OpenCV库或其他图像处理工具来加载并预处理CT图像,可能包括灰度化、二值化、噪声去除等步骤[^1]。 1. **图像预处理**: ```python import cv2 img = cv2.imread('ct_image_path.jpg', cv2.IMREAD_GRAYSCALE) _, binary_img = cv2.threshold(img, threshold, 255, cv2.THRESH_BINARY_INV) ``` 2. **特征提取**: 使用像Canny边缘检测或Hough变换来突出显示可能的裂缝边缘。 3. **分割与标记**: 对检测到的边缘进行细化或连接组件分析,以分离单独的缺陷区域。 4. **特征描述和选择**: 应用特征如纹理、形状或大小信息,利用诸如局部二值模式(LBP)或霍夫关键点(Harris角点)来量化这些特征。 5. **机器学习**: 使用训练过的模型(如支持向量机(SVM)、随机森林(RF)或最近几年流行的深度学习模型)来对特征进行分类,区分正常木材和有缺陷的部分。如果使用深度学习,可以考虑卷积神经网络(CNN)来自动从原始像素级别学习特征。 6. **评估与优化**: 通过交叉验证和调整超参数,提升模型性能,最后可能还需要进行后期处理,如后验概率阈值调整,以确定最终的缺陷区域。 请注意,实际应用中可能需要大量的标注数据来训练模型,而且每个阶段的具体实现可能会根据具体需求和数据特点有所不同。如果你正在处理的是医疗影像,可能还需要遵循相关的隐私法规和伦理准则。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值