我想使用Xamarin.Android应用创建电话上所有呼叫(传入和传出)的自定义列表。但是我无法使此解决方案按要求工作。主要问题在于,监视Phone.State的广播接收器永远不会收到有关呼入和呼出电话的通知。我也尝试了与该问题有关的stackoverflow上的大多数链接,但均无济于事,这是我当前的源代码;
[assembly: UsesPermission(Manifest.Permission.ReadCallLog)]
[assembly: UsesPermission(Manifest.Permission.ReadPhoneNumbers)]
[assembly: UsesPermission(Manifest.Permission.ReadPhoneState)]
[assembly: UsesPermission(Manifest.Permission.ProcessOutgoingCalls)]
[assembly: UsesPermission(Manifest.Permission.ReadExternalStorage)]
[assembly: UsesPermission(Manifest.Permission.WriteExternalStorage)]
namespace IncomingOutgoingCall
{
[Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
#region Private Properties
IncomingOutgoingBroadcastReceiver callReceiver;
int REQUEST_PERMISSION_CODE = 1003;
#endregion
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
RequestPermission(Manifest.Permission.ReadPhoneState, Manifest.Permission.ProcessOutgoingCalls, Manifest.Permission.ReadPhoneNumbers, Manifest.Permission.WriteExternalStorage, Manifest.Permission.ReadExternalStorage);
callReceiver = new IncomingOutgoingBroadcastReceiver();
var callMonitorIntent = new Intent(ApplicationContext, typeof(IncomingOutgoingBroadcastReceiver));
// SendBroadcast(callMonitorIntent);
}
public void RequestPermission(params string[] permissions)
{
// Request required permission
ActivityCompat.RequestPermissions(this, permissions, REQUEST_PERMISSION_CODE);
}
}
[BroadcastReceiver(Name = "com.callmonitor.app.IncomingOutgoingBroadcastReceiver", Enabled = true, Exported = false)]
[IntentFilter(new[] { TelephonyManager.ActionPhoneStateChanged, "android.intent.action.PHONE_STATE", "android.intent.action.NEW_OUTGOING_CALL" }, Priority = (int)IntentFilterPriority.HighPriority)]
public class IncomingOutgoingBroadcastReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
string dirPath = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath + "/" + AppInfo.Name;
if (!Directory.Exists(dirPath))
{
Directory.CreateDirectory(dirPath);
string filePath = Path.Combine(dirPath, "logFile.txt");
if (!File.Exists(filePath))
File.Create(filePath);
using (StreamWriter sw = new StreamWriter(filePath))
{
// Code to register call information omitted
}
}
}
}
}
这是我的android清单文件
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.callmonitor" android:installLocation="auto">
<uses-sdk android:minSdkVersion="15" android:targetSdkVersion="27" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_CALL_LOG" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme" android:label="CallMonitor"></application>
</manifest>
[如果有人对经过测试和工作的解决方案具有链接/建议,我想尝试一下。
似乎从BroadcastReceiver中读取电话记录并不容易,读取电话记录的最佳方法是通过Cursor从Android数据库中读取。
public IEnumerable<CallLogModel> GetCallLogs()
{
var phoneContacts = new List<CallLogModel>();
// filter in desc order limit by no
string querySorter = String.Format("{0} desc ", CallLog.Calls.Date);
using (var phones = Android.App.Application.Context.ContentResolver.Query(CallLog.Calls.ContentUri, null, null, null, querySorter))
{
if (phones != null)
{
while (phones.MoveToNext())
{
try
{
string callNumber = phones.GetString(phones.GetColumnIndex(CallLog.Calls.Number));
string callDuration = phones.GetString(phones.GetColumnIndex(CallLog.Calls.Duration));
long callDate = phones.GetLong(phones.GetColumnIndex(CallLog.Calls.Date));
string callName = phones.GetString(phones.GetColumnIndex(CallLog.Calls.CachedName));
int callTypeInt = phones.GetInt(phones.GetColumnIndex(CallLog.Calls.Type));
string callType = Enum.GetName(typeof(CallType), callTypeInt);
var log = new CallLogModel();
log.CallName = callName;
log.CallNumber = callNumber;
log.CallDuration = callDuration;
log.CallDateTick = callDate;
log.CallType = callType;
phoneContacts.Add(log);
}
catch (Exception ex)
{
//something wrong with one contact, may be display name is completely empty, decide what to do
}
}
phones.Close();
}
// if we get here, we can't access the contacts. Consider throwing an exception to display to the user
}
return phoneContacts;
}
这是您可以查看的示例: