问题描述
我创建一个应用程序,在那里我得到的通话记录中的 列表视图
的,现在我试图为之后的任何传入或传出呼叫断开,我想打开的 列表视图
的,但我不知道我的应用程序是不开放。我的 列表视图
的没有任何呼叫后显示的页面,以下是我的code
公共类MainActivity延伸活动{ 私人的ListView列表视图= NULL;
私人字符串CALLTYPE = NULL;
私人字符串phoneNumber的= NULL;
私人字符串callDate = NULL;
私人字符串callDuration = NULL;
私人日期callDateTime = NULL; 私人列表< CallData>名单=新的ArrayList< CallData>();
私人上下文的背景下= NULL;
@覆盖
保护无效的onCreate(捆绑savedInstanceState){
super.onCreate(savedInstanceState);
的setContentView(R.layout.activity_main);
上下文=这一点; 列表视图=(ListView控件)findViewById(R.id.listView_calldata); getCallDetails();
CustomAdapter适配器=新CustomAdapter(MainActivity.this,清单);
listview.setAdapter(适配器);
} 公共无效getCallDetails()
{ 光标managedCursor = getContentResolver()查询(CallLog.Calls.CONTENT_URI,NULL,NULL,NULL,NULL); INT数= managedCursor.getColumnIndex(CallLog.Calls.NUMBER);
整型= managedCursor.getColumnIndex(CallLog.Calls.TYPE);
INT日期= managedCursor.getColumnIndex(CallLog.Calls.DATE);
INT持续时间= managedCursor.getColumnIndex(CallLog.Calls.DURATION);
而(managedCursor.moveToNext())
{ phoneNumber的= managedCursor.getString(数);
CALLTYPE = managedCursor.getString(类型);
callDate = managedCursor.getString(日期); callDateTime =新的日期(Long.valueOf(callDate)); callDuration = managedCursor.getString(持续时间); 字符串CTYPE = NULL; INT CTYPE code =的Integer.parseInt(CALLTYPE); 开关(CTYPE code)
{
案例CallLog.Calls.OUTGOING_TYPE:
CTYPE =离开;
打破; 案例CallLog.Calls.INCOMING_TYPE:
CTYPE =进入;
打破; 案例CallLog.Calls.MISSED_TYPE:
CTYPE =漏;
打破;
} CallData calldata =新CallData(CTYPE,phoneNumber的,callDateTime,callDuration);
list.add(calldata);
} managedCursor.close();
}
}
PhoneCallReceiver
公共抽象类PhonecallReceiver扩展广播接收器{ //每当Android的感觉就像是,接收器将被重新创建。我们需要一个静态变量来记住实例之间的数据
静态PhonecallStartEndDetector侦听器;
串outgoingSavedNumber;
受保护的语境savedContext;
@覆盖
公共无效的onReceive(上下文的背景下,意图意图){
savedContext =背景;
如果(听众== NULL){
听众=新PhonecallStartEndDetector();
} //我们听两个目的。新的呼出只告诉我们一个呼出。我们用它来获得的数目。
如果(intent.getAction()。等于(android.intent.action.NEW_OUTGOING_CALL)){
listener.setOutgoingNumber(intent.getExtras()的getString(android.intent.extra.PHONE_NUMBER)。);
返回;
} //其他的意图告诉我们,手机状态改变。这里我们设置一个监听器来处理它
TelephonyManager电话=(TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
telephony.listen(监听器,PhoneStateListener.LISTEN_CALL_STATE);
} //派生类应覆盖这些对感兴趣的特定事件作出回应
受保护的抽象无效onIncomingCallStarted(串号,日期开始);
受保护的抽象无效onOutgoingCallStarted(串号,日期开始);
受保护的抽象无效onIncomingCallEnded(串号,开始日期,结束日期);
受保护的抽象无效onOutgoingCallEnded(串号,开始日期,结束日期);
受保护的抽象无效onMissedCall(串号,日期开始); //实际的活动优惠
公共类PhonecallStartEndDetector扩展PhoneStateListener {
INT lastState = TelephonyManager.CALL_STATE_IDLE;
日期callStartTime;
布尔isIncoming;
串savedNumber; //因为传递进来的是只有在有效振铃 公共PhonecallStartEndDetector(){} //即将离任的数量仅通过一个单独的意图发出的,所以我们需要将其存储带外
公共无效setOutgoingNumber(串号){
savedNumber =号;
} //传入call-从IDLE进入响起时,振铃,摘机来时,它的回答,当其吊起来IDLE
//传出call-从IDLE变为摘机时,拨出,当吊起来IDLE
@覆盖
公共无效onCallStateChanged(INT状态,弦乐incomingNumber){
super.onCallStateChanged(州,incomingNumber);
如果(lastState ==州){
//没有变化,反跳演员
返回;
}
开关(州){
案例TelephonyManager.CALL_STATE_RINGING:
isIncoming = TRUE;
callStartTime =新的日期();
savedNumber = incomingNumber;
onIncomingCallStarted(incomingNumber,callStartTime);
打破;
案例TelephonyManager.CALL_STATE_OFFHOOK:
的ringing-&GT //过渡;摘机是来电的皮卡。没有donw他们
如果(lastState!= TelephonyManager.CALL_STATE_RINGING){
isIncoming = FALSE;
callStartTime =新的日期();
onOutgoingCallStarted(savedNumber,callStartTime);
}
打破;
案例TelephonyManager.CALL_STATE_IDLE:
//走到idle-这是一个呼叫的结束。什么类型取决于previous状态(S)
如果(lastState == TelephonyManager.CALL_STATE_RINGING){
//戒指,但没有接听 - 思念
onMissedCall(savedNumber,callStartTime);
}
否则,如果(isIncoming){
onIncomingCallEnded(savedNumber,callStartTime,新的Date());
}
其他{
onOutgoingCallEnded(savedNumber,callStartTime,新的Date());
}
打破;
}
lastState =状态;
} }
清单
<清单的xmlns:机器人=http://schemas.android.com/apk/res/android
包=com.example.tests
安卓版code =1
机器人:=的versionName1.0> <用途-SDK
安卓的minSdkVersion =8
机器人:targetSdkVersion =21/>
<使用许可权的android:NAME =android.permission.READ_CONTACTS/> <使用许可权的android:NAME =android.permission.READ_PHONE_STATE/>
<使用许可权的android:NAME =android.permission.PROCESS_OUTGOING_CALLS/>
<应用
机器人:allowBackup =真
机器人:图标=@绘制/ ic_launcher
机器人:标签=@字符串/ APP_NAME
机器人:主题=@风格/ AppTheme>
<接收机器人:名字=。PhonecallReceiver>
&所述;意图滤光器>
<作用机器人:名字=android.intent.action.PHONE_STATE/>
&所述; /意图滤光器>
&所述;意图滤光器>
<作用机器人:名字=android.intent.action.NEW_OUTGOING_CALL/>
&所述; /意图滤光器>
< /接收器> <! - 这一部分是应用程序内部 - > <活动
机器人:名字=。MainActivity
机器人:标签=@字符串/ APP_NAME> &所述;意图滤光器>
<作用机器人:名字=android.intent.action.MAIN/> <类机器人:名字=android.intent.category.LAUNCHER/>
&所述; /意图滤光器> < /活性GT;
< /用途>< /清单>
您已经声明了 PhonecallReceiver
为摘要
。这意味着,当它需要的Android无法实例化。你需要重新考虑你的架构。 广播接收器
■在清单中声明不能摘要
由于Android需要能够根据需要实例化它们本身。要么让你的 PhonecallReceiver
混凝土(不是抽象的),或添加具体子类为<接收>
在清单。
I am creating an application, where I am getting call history in a listview
, now what I am trying is after any incoming or outgoing call disconnection,I want to open that listview
, but I don't know my app is not opening. my listview
page is not displayed after any call, following is my code
public class MainActivity extends Activity {
private ListView listview=null;
private String callType=null;
private String phoneNumber=null;
private String callDate=null;
private String callDuration=null;
private Date callDateTime=null;
private List<CallData> list=new ArrayList<CallData>();
private Context context=null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context=this;
listview=(ListView)findViewById(R.id.listView_calldata);
getCallDetails();
CustomAdapter adapter=new CustomAdapter(MainActivity.this, list);
listview.setAdapter(adapter);
}
public void getCallDetails()
{
Cursor managedCursor = getContentResolver().query(CallLog.Calls.CONTENT_URI,null, null,null, null);
int number = managedCursor.getColumnIndex( CallLog.Calls.NUMBER );
int type = managedCursor.getColumnIndex( CallLog.Calls.TYPE );
int date = managedCursor.getColumnIndex( CallLog.Calls.DATE);
int duration = managedCursor.getColumnIndex( CallLog.Calls.DURATION);
while (managedCursor.moveToNext())
{
phoneNumber = managedCursor.getString(number);
callType = managedCursor.getString(type);
callDate = managedCursor.getString(date);
callDateTime = new Date(Long.valueOf(callDate));
callDuration = managedCursor.getString(duration);
String cType = null;
int cTypeCode = Integer.parseInt(callType);
switch(cTypeCode)
{
case CallLog.Calls.OUTGOING_TYPE:
cType = "OUTGOING";
break;
case CallLog.Calls.INCOMING_TYPE:
cType= "INCOMING";
break;
case CallLog.Calls.MISSED_TYPE:
cType = "MISSED";
break;
}
CallData calldata=new CallData(cType, phoneNumber, callDateTime, callDuration);
list.add(calldata);
}
managedCursor.close();
}
}
PhoneCallReceiver
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
static PhonecallStartEndDetector listener;
String outgoingSavedNumber;
protected Context savedContext;
@Override
public void onReceive(Context context, Intent intent) {
savedContext = context;
if(listener == null){
listener = new PhonecallStartEndDetector();
}
//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")) {
listener.setOutgoingNumber(intent.getExtras().getString("android.intent.extra.PHONE_NUMBER"));
return;
}
//The other intent tells us the phone state changed. Here we set a listener to deal with it
TelephonyManager telephony = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
telephony.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
}
//Derived classes should override these to respond to specific events of interest
protected abstract void onIncomingCallStarted(String number, Date start);
protected abstract void onOutgoingCallStarted(String number, Date start);
protected abstract void onIncomingCallEnded(String number, Date start, Date end);
protected abstract void onOutgoingCallEnded(String number, Date start, Date end);
protected abstract void onMissedCall(String number, Date start);
//Deals with actual events
public class PhonecallStartEndDetector extends PhoneStateListener {
int lastState = TelephonyManager.CALL_STATE_IDLE;
Date callStartTime;
boolean isIncoming;
String savedNumber; //because the passed incoming is only valid in ringing
public PhonecallStartEndDetector() {}
//The outgoing number is only sent via a separate intent, so we need to store it out of band
public void setOutgoingNumber(String number){
savedNumber = number;
}
//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
@Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
if(lastState == state){
//No change, debounce extras
return;
}
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
isIncoming = true;
callStartTime = new Date();
savedNumber = incomingNumber;
onIncomingCallStarted(incomingNumber, callStartTime);
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
//Transition of ringing->offhook are pickups of incoming calls. Nothing donw on them
if(lastState != TelephonyManager.CALL_STATE_RINGING){
isIncoming = false;
callStartTime = new Date();
onOutgoingCallStarted(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(savedNumber, callStartTime);
}
else if(isIncoming){
onIncomingCallEnded(savedNumber, callStartTime, new Date());
}
else{
onOutgoingCallEnded(savedNumber, callStartTime, new Date());
}
break;
}
lastState = state;
}
}
Manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.tests"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<receiver android:name=".PhonecallReceiver" >
<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>
<!--This part is inside the application-->
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
You have declared your PhonecallReceiver
as abstract
. This means that Android cannot instantiate it when it needs to. You need to rethink your architecture. BroadcastReceiver
s declared in the manifest cannot be abstract
because Android needs to be able to instantiate them itself as needed. Either make your PhonecallReceiver
concrete (not abstract), or add the concrete subclasses as <receiver>
in the manifest.
这篇关于开放式应用传入或传出呼叫diconnection后的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!