在我的应用程序中,我已使用广播接收器获取传入的电话号码,并将其显示在对话框中,然后单击按钮将其保存在应用程序中。每次通话结束后获取号码。 Oreo和Pie以下的所有android版本都可以正常工作。在“奥利奥和派(Oreo and Pie)”中,关闭/杀死该应用程序后,结束通话后不会出现对话框。但是当应用程序运行时,对话框会完美显示。我认为当我们终止该应用程序时,广播接收器也会被终止。我一直在搜索几天,但没有帮助。
这是我的代码的一些介绍:
Manifest.xml:
<receiver
android:name="com.softixtechnologies.phonemanager.callhelpers.CallReciever"
android:enabled="true">
<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>
MainActivity.java:
public class MainActivity extends AppCompatActivity {
LinearLayout btncat, btnlog, btnIgnore, btnExit;
SwitchCompat checkBoxMissed, checkBoxUnknown ;
boolean isCheckedValue = true;
boolean isCheckedUnknown = true;
DatabaseHelper databaseHelper ;
public static final String SHARED_PREFS = "shared_prefs" ;
public final static int MY_PERMISSIONS_REQUEST_READ_PHONE_STATE = 11;
public static int ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE = 5469;
public static final int CALL_LOG_PERMISSION = 1 ;
PhoneCallReceiver phoneCallReceiver ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
databaseHelper = new DatabaseHelper(this) ;
btncat = findViewById(R.id.button_Categories);
btnlog = findViewById(R.id.button_logs) ;
btnIgnore = findViewById(R.id.button_Ignore_contacts) ;
checkBoxMissed= findViewById(R.id.checkbox_missed) ;
checkBoxUnknown= findViewById(R.id.checkbox_unknown);
btnExit = findViewById(R.id.button_exit);
phoneCallReceiver = new PhoneCallReceiver();
IntentFilter intentFilter = new IntentFilter();
// intentFilter.addAction("android.intent.action.PHONE_STATE");
// intentFilter.addAction("android.intent.action.NEW_OUTGOING_CALL");
IntentFilter intentFilter1 = new IntentFilter("android.intent.action.NEW_OUTGOING_CALL");
intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
intentFilter1.addCategory(Intent.CATEGORY_DEFAULT);
registerReceiver(phoneCallReceiver, intentFilter);
registerReceiver(phoneCallReceiver, intentFilter1);
checkPermission();
requestCallLogPermission();
//permission check for pie 23-july-2019
if (ContextCompat.checkSelfPermission(this,Manifest.permission.READ_CALL_LOG) == PackageManager.PERMISSION_GRANTED){
}else {
requestCallLogPermission();
}
if (ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.READ_PHONE_STATE)
!= PackageManager.PERMISSION_GRANTED)
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.READ_CONTACTS)) {
} else {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_PHONE_STATE, Manifest.permission.SYSTEM_ALERT_WINDOW},
MY_PERMISSIONS_REQUEST_READ_PHONE_STATE);
}
SharedPreferences sharedPreferenceCAT = getSharedPreferences(SHARED_PREFS, MODE_PRIVATE);
boolean isFirstTimeCAT =sharedPreferenceCAT.getBoolean("isFirstTimeCAT", true);
if (isFirstTimeCAT){
try{
databaseHelper.insertCAT("New Customer");
databaseHelper.insertCAT("Complaint");
databaseHelper.insertCAT("Reminder");
sharedPreferenceCAT.edit().putBoolean("isFirstTimeCAT",false).commit();}catch (Exception e){
Toast.makeText(this, ""+ e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
final SharedPreferences.Editor editor = preferences.edit();
checkBoxMissed.setChecked(preferences.getBoolean("checked",false));
checkBoxMissed.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
isCheckedValue = isChecked;
editor.putBoolean("checked", isChecked);
editor.apply();
}
});
SharedPreferences preferencesUnknown = PreferenceManager.getDefaultSharedPreferences(this);
final SharedPreferences.Editor editorUnknown = preferencesUnknown.edit();
checkBoxUnknown.setChecked(preferencesUnknown.getBoolean("checkedunknown",false));
checkBoxUnknown.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
isCheckedUnknown = isChecked;
editorUnknown.putBoolean("checkedunknown", isChecked);
editorUnknown.apply();
}
});
private void requestCallLogPermission() {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_CALL_LOG)){
new AlertDialog.Builder(this).setTitle("Permission Needed")
.setMessage("This permission is needed by App to work properly !")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions(MainActivity.this, new String[] {Manifest.permission.READ_CALL_LOG},
CALL_LOG_PERMISSION);
}
}).setCancelable(false)
.create().show();
}else {
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.READ_CALL_LOG},
CALL_LOG_PERMISSION);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch(requestCode){
case MY_PERMISSIONS_REQUEST_READ_PHONE_STATE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
}else {
return;
}
case CALL_LOG_PERMISSION:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "Call Log Permission Granted !", Toast.LENGTH_SHORT).show();
}
}
}
@TargetApi(Build.VERSION_CODES.M)
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE) {
if (!Settings.canDrawOverlays(this)) {
// You don't have permission
checkPermission();
} else {
// Do as per your logic
}
}
if (requestCode == CALL_LOG_PERMISSION) {
if (!Settings.canDrawOverlays(this)) {
// You don't have permission
requestCallLogPermission();
} else {
// Do as per your logic
}
}
}
public void checkPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Settings.canDrawOverlays(this)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE);
}
}
}
@Override
protected void onStart() {
super.onStart();
IntentFilter intentFilter = new IntentFilter("android.intent.action.PHONE_STATE");
IntentFilter intentFilter1 = new IntentFilter("android.intent.action.NEW_OUTGOING_CALL");
intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
intentFilter1.addCategory(Intent.CATEGORY_DEFAULT);
registerReceiver(phoneCallReceiver, intentFilter);
registerReceiver(phoneCallReceiver, intentFilter1);
}
@Override
protected void onStop() {
super.onStop();
// unregisterReceiver(phoneCallReceiver);
}
@Override
protected void onDestroy() {
super.onDestroy();
}
}
BroadCast接收器:
public class PhoneCallReceiver extends BroadcastReceiver {
private static int lastState = TelephonyManager.CALL_STATE_IDLE;
private static Date callStartTime;
private static boolean isIncoming;
private static String savedNumber;
@Override
public void onReceive(final Context context, Intent intent) {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.P){
TelephonyManager tm = (TelephonyManager)context.getSystemService(Service.TELEPHONY_SERVICE);
switch (tm.getCallState()) {
case TelephonyManager.CALL_STATE_IDLE:
Toast.makeText(context, "IDLE", Toast.LENGTH_SHORT).show();
final String phoneNr= intent.getStringExtra("incoming_number");
Toast.makeText(context, phoneNr,Toast.LENGTH_LONG).show();
SharedPreferences preferencesUnknown = PreferenceManager.getDefaultSharedPreferences(context);
final SharedPreferences.Editor editorUnknown = preferencesUnknown.edit();
boolean checkedUnknown = preferencesUnknown.getBoolean("checkedunknown", false);
if (checkedUnknown) {
boolean isUnknown = contactExists(context, phoneNr);
if (isUnknown == false) {
AlertDialog.Builder alerDialog = new AlertDialog.Builder(context);
alerDialog.setIcon(R.drawable.calllogo);
alerDialog.setTitle(phoneNr);
alerDialog.setMessage("Save this number ?");
alerDialog.setCancelable(false);
alerDialog.setPositiveButton("YES", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(context, CategoryPhoneActivity.class);
intent.putExtra("Phone", phoneNr);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
});
alerDialog.setNegativeButton("NO", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
AlertDialog aldialog = alerDialog.create();
aldialog.setCanceledOnTouchOutside(false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
aldialog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY); } else {
aldialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
}
aldialog.show(); } else {
Toast.makeText(context, "Number is already saved", Toast.LENGTH_SHORT).show(); }
}else{
AlertDialog.Builder alerDialog = new AlertDialog.Builder(context);
alerDialog.setIcon(R.drawable.calllogo);
alerDialog.setTitle(phoneNr);
alerDialog.setCancelable(false);
alerDialog.setMessage("Save this number ?");
alerDialog.setPositiveButton("YES", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(context, CategoryPhoneActivity.class);
intent.putExtra("Phone", phoneNr);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
});
alerDialog.setNegativeButton("NO", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
AlertDialog aldialog = alerDialog.create();
aldialog.setCanceledOnTouchOutside(false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
aldialog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY); } else {
aldialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
}
aldialog.show(); }
break;
}
}else {
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);
}
}
}
protected void onIncomingCallStarted(Context ctx, String number, Date start){}
protected void onOutgoingCallStarted(Context ctx, String number, Date start){}
protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end){}
protected void onOutgoingCallEnded(Context ctx, String number, Date start, Date end){}
protected void onMissedCall(Context ctx, String number, Date start){}
public void onCallStateChanged(Context context, int state, String number) {
if(lastState == state){
return;
}
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
isIncoming = true;
callStartTime = new Date();
savedNumber = number;
onIncomingCallStarted(context, number, callStartTime);
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
if(lastState != TelephonyManager.CALL_STATE_RINGING){
isIncoming = false;
callStartTime = new Date();
onOutgoingCallStarted(context, savedNumber, callStartTime);
}
break;
case TelephonyManager.CALL_STATE_IDLE:
if(lastState == TelephonyManager.CALL_STATE_RINGING){
onMissedCall(context, savedNumber, callStartTime);
}
else if(isIncoming){
onIncomingCallEnded(context, savedNumber, callStartTime, new Date());
}
else{
onOutgoingCallEnded(context, savedNumber, callStartTime, new Date());
}
break;
}
lastState = state;
}
CallReceiver:
public class CallReciever extends PhoneCallReceiver {
DatabaseHelper databaseHelper ;
@Override
protected void onIncomingCallStarted(final Context ctx, final String number, Date start) {
}
@Override
protected void onOutgoingCallStarted(Context ctx, String number, Date start) {
}
@Override
protected void onIncomingCallEnded(final Context ctx, final String number, Date start, Date end) {
SharedPreferences preferencesUnknown = PreferenceManager.getDefaultSharedPreferences(ctx);
final SharedPreferences.Editor editorUnknown = preferencesUnknown.edit();
boolean checkedUnknown = preferencesUnknown.getBoolean("checkedunknown", false);
if (checkedUnknown) {
boolean isUnknown = contactExists(ctx, number);
if (isUnknown == false) {
AlertDialog.Builder alerDialog = new AlertDialog.Builder(ctx);
alerDialog.setIcon(R.drawable.calllogo);
alerDialog.setTitle(number);
alerDialog.setMessage("Save this number ?");
alerDialog.setCancelable(false);
alerDialog.setPositiveButton("YES", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(ctx, CategoryPhoneActivity.class);
intent.putExtra("Phone", number);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ctx.startActivity(intent);
}
});
alerDialog.setNegativeButton("NO", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
AlertDialog aldialog = alerDialog.create();
aldialog.setCanceledOnTouchOutside(false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
aldialog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY); } else {
aldialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
}
aldialog.show(); } else {
Toast.makeText(ctx, "Number is already saved", Toast.LENGTH_SHORT).show(); }
}else{
AlertDialog.Builder alerDialog = new AlertDialog.Builder(ctx);
alerDialog.setIcon(R.drawable.calllogo);
alerDialog.setTitle(number);
alerDialog.setCancelable(false);
alerDialog.setMessage("Save this number ?");
alerDialog.setPositiveButton("YES", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(ctx, CategoryPhoneActivity.class);
intent.putExtra("Phone", number);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ctx.startActivity(intent);
}
});
alerDialog.setNegativeButton("NO", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
AlertDialog aldialog = alerDialog.create();
aldialog.setCanceledOnTouchOutside(false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
aldialog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY); } else {
aldialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
}
aldialog.show(); }
}
@Override
protected void onOutgoingCallEnded(Context ctx, String number, Date start, Date end) {
}
@Override
protected void onMissedCall(final Context ctx, final String number, Date start) {
Toast.makeText(ctx, "Missed call from " + number, Toast.LENGTH_SHORT).show();
databaseHelper = new DatabaseHelper(ctx);
if (databaseHelper.searchContact(number)){
return;
}
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(ctx);
final SharedPreferences.Editor editor = preferences.edit();
boolean checked = preferences.getBoolean("checked", false);
if (checked) {
SharedPreferences preferencesUnknown = PreferenceManager.getDefaultSharedPreferences(ctx);
final SharedPreferences.Editor editorUnknown = preferencesUnknown.edit();
boolean checkedUnknown = preferencesUnknown.getBoolean("checkedunknown", false);
if (checkedUnknown) {
boolean isUnknown = contactExists(ctx, number);
if (isUnknown == false) {
AlertDialog.Builder alerDialog = new AlertDialog.Builder(ctx);
alerDialog.setIcon(R.drawable.calllogo);
alerDialog.setTitle(number);
alerDialog.setMessage("Save this number ?");
alerDialog.setPositiveButton("YES", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(ctx, CategoryPhoneActivity.class);
intent.putExtra("Phone", number);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ctx.startActivity(intent);
}
});
alerDialog.setNegativeButton("NO", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
AlertDialog aldialog = alerDialog.create();
aldialog.setCanceledOnTouchOutside(false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
aldialog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY); } else {
aldialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
}
aldialog.show(); } else {
Toast.makeText(ctx, "Number is already saved", Toast.LENGTH_SHORT).show(); }
}else{
AlertDialog.Builder alerDialog = new AlertDialog.Builder(ctx);
alerDialog.setIcon(R.drawable.calllogo);
alerDialog.setTitle(number);
alerDialog.setMessage("Save this number ?");
alerDialog.setPositiveButton("YES", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(ctx, CategoryPhoneActivity.class);
intent.putExtra("Phone", number);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ctx.startActivity(intent);
}
});
alerDialog.setNegativeButton("NO", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
AlertDialog aldialog = alerDialog.create();
aldialog.setCanceledOnTouchOutside(false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
aldialog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY); } else {
aldialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
}
aldialog.show(); }
}else{
Toast.makeText(ctx, "", Toast.LENGTH_SHORT).show(); }
}
public boolean contactExists(Context context, String number) {
Uri lookupUri = Uri.withAppendedPath(
ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
Uri.encode(number));
String[] mPhoneNumberProjection = { ContactsContract.PhoneLookup._ID, ContactsContract.PhoneLookup.NUMBER, ContactsContract.PhoneLookup.DISPLAY_NAME };
Cursor cur = context.getContentResolver().query(lookupUri,mPhoneNumberProjection, null, null, null);
try {
if (cur.moveToFirst()) {
return true;
}
} finally {
if (cur != null)
cur.close();
}
return false;
}
}
答案 0 :(得分:-1)
从Android 8.0(API级别26)开始,系统强加 对清单声明的接收者的其他限制。
如果您的应用程序针对Android 8.0或更高版本,则不能使用清单 声明大多数隐式广播的接收方( (不专门针对您的应用)。您仍然可以使用 用户正在积极使用您的应用程序时,上下文注册的接收器。
我猜您关闭应用程序后,系统会自动注销您的broadcast receivers
。
解决方案:创建即时贴或前台服务,然后在服务中注册您的广播接收器。当您接收广播时,从广播接收器onReceive
启动活动并显示对话框。