mirror of
https://gitlab.com/xynngh/YetAnotherCallBlocker.git
synced 2025-02-16 11:50:39 +01:00
Add "advanced call blocking mode"
CallScreeningService-based blocking available on Android 7+
This commit is contained in:
parent
55b8c57264
commit
1dd983ac27
@ -1,7 +1,7 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
compileSdkVersion 29
|
||||
defaultConfig {
|
||||
applicationId "dummydomain.yetanothercallblocker"
|
||||
minSdkVersion 14
|
||||
|
@ -59,6 +59,27 @@
|
||||
android:noHistory="true"
|
||||
android:theme="@style/DialogBackgroundTheme" />
|
||||
|
||||
<activity
|
||||
android:name=".DummyDialerActivity"
|
||||
android:autoRemoveFromRecents="true"
|
||||
android:excludeFromRecents="true"
|
||||
android:noHistory="true"
|
||||
android:theme="@style/DialogBackgroundTheme">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<action android:name="android.intent.action.DIAL" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="tel" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.DIAL" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<receiver
|
||||
android:name=".CallReceiver"
|
||||
android:enabled="true"
|
||||
@ -69,6 +90,14 @@
|
||||
</receiver>
|
||||
|
||||
<service android:name=".work.TaskService" />
|
||||
|
||||
<service
|
||||
android:name=".CallScreeningServiceImpl"
|
||||
android:permission="android.permission.BIND_SCREENING_SERVICE">
|
||||
<intent-filter>
|
||||
<action android:name="android.telecom.CallScreeningService" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
</application>
|
||||
|
||||
</manifest>
|
@ -24,6 +24,7 @@ import dummydomain.yetanothercallblocker.event.CallOngoingEvent;
|
||||
import dummydomain.yetanothercallblocker.event.CallStartedEvent;
|
||||
|
||||
import static dummydomain.yetanothercallblocker.EventUtils.postEvent;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public class CallReceiver extends BroadcastReceiver {
|
||||
|
||||
@ -81,9 +82,11 @@ public class CallReceiver extends BroadcastReceiver {
|
||||
@SuppressLint("MissingPermission")
|
||||
private boolean rejectCall(@NonNull Context context) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
TelecomManager telecomManager = (TelecomManager)
|
||||
context.getSystemService(Context.TELECOM_SERVICE);
|
||||
try {
|
||||
TelecomManager telecomManager = requireNonNull(
|
||||
(TelecomManager) context.getSystemService(Context.TELECOM_SERVICE));
|
||||
|
||||
//noinspection deprecation
|
||||
telecomManager.endCall();
|
||||
LOG.info("Rejected call using TelecomManager");
|
||||
|
||||
@ -93,12 +96,14 @@ public class CallReceiver extends BroadcastReceiver {
|
||||
}
|
||||
}
|
||||
|
||||
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
try {
|
||||
TelephonyManager tm = requireNonNull(
|
||||
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE));
|
||||
|
||||
@SuppressLint("DiscouragedPrivateApi") // no choice
|
||||
Method m = tm.getClass().getDeclaredMethod("getITelephony");
|
||||
m.setAccessible(true);
|
||||
ITelephony telephony = (ITelephony)m.invoke(tm);
|
||||
ITelephony telephony = requireNonNull((ITelephony) m.invoke(tm));
|
||||
|
||||
telephony.endCall();
|
||||
LOG.info("Rejected call using ITelephony");
|
||||
|
@ -0,0 +1,89 @@
|
||||
package dummydomain.yetanothercallblocker;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.telecom.Call;
|
||||
import android.telecom.CallScreeningService;
|
||||
import android.telecom.PhoneAccount;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import dummydomain.yetanothercallblocker.data.DatabaseSingleton;
|
||||
import dummydomain.yetanothercallblocker.data.NumberInfo;
|
||||
import dummydomain.yetanothercallblocker.event.CallEndedEvent;
|
||||
|
||||
import static dummydomain.yetanothercallblocker.EventUtils.postEvent;
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.N)
|
||||
public class CallScreeningServiceImpl extends CallScreeningService {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(CallScreeningServiceImpl.class);
|
||||
|
||||
@Override
|
||||
public void onScreenCall(@NonNull Call.Details callDetails) {
|
||||
LOG.info("onScreenCall({})", callDetails);
|
||||
|
||||
boolean shouldBlock = false;
|
||||
NumberInfo numberInfo = null;
|
||||
|
||||
try {
|
||||
boolean ignore = false;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
if (callDetails.getCallDirection() != Call.Details.DIRECTION_INCOMING) {
|
||||
ignore = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ignore && !App.getSettings().getBlockCalls()) {
|
||||
ignore = true;
|
||||
}
|
||||
|
||||
if (!ignore) {
|
||||
Uri handle = callDetails.getHandle();
|
||||
if (PhoneAccount.SCHEME_TEL.equals(handle.getScheme())) {
|
||||
String number = handle.getSchemeSpecificPart();
|
||||
LOG.debug("onScreenCall() number={}", number);
|
||||
|
||||
numberInfo = DatabaseSingleton.getNumberInfo(number);
|
||||
|
||||
if (numberInfo.rating == NumberInfo.Rating.NEGATIVE
|
||||
&& numberInfo.contactItem == null) {
|
||||
shouldBlock = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
LOG.debug("onScreenCall() blocking call: {}", shouldBlock);
|
||||
|
||||
CallScreeningService.CallResponse.Builder responseBuilder = new CallResponse.Builder();
|
||||
|
||||
if (shouldBlock) {
|
||||
responseBuilder
|
||||
.setDisallowCall(true)
|
||||
.setRejectCall(true)
|
||||
.setSkipNotification(true);
|
||||
}
|
||||
|
||||
boolean blocked = shouldBlock;
|
||||
try {
|
||||
respondToCall(callDetails, responseBuilder.build());
|
||||
} catch (Exception e) {
|
||||
LOG.error("onScreenCall() error invoking respondToCall()", e);
|
||||
blocked = false;
|
||||
}
|
||||
|
||||
if (blocked) {
|
||||
LOG.info("onScreenCall() blocked call");
|
||||
|
||||
NotificationHelper.showBlockedCallNotification(this, numberInfo);
|
||||
|
||||
postEvent(new CallEndedEvent());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package dummydomain.yetanothercallblocker;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class DummyDialerActivity extends AppCompatActivity {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(DummyDialerActivity.class);
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Intent intent = getIntent();
|
||||
LOG.info("onCreate() intent: {}", intent);
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
||||
return; // not applicable to earlier versions
|
||||
}
|
||||
|
||||
intent.setComponent(null);
|
||||
|
||||
ActivityInfo found = null;
|
||||
|
||||
for (ResolveInfo info : getPackageManager()
|
||||
.queryIntentActivities(intent, PackageManager.MATCH_ALL)) {
|
||||
ActivityInfo activityInfo = info.activityInfo;
|
||||
if (activityInfo != null && activityInfo.applicationInfo.enabled
|
||||
&& !activityInfo.packageName.equals(BuildConfig.APPLICATION_ID)) {
|
||||
LOG.debug("onCreate() found match: {}", activityInfo);
|
||||
found = activityInfo;
|
||||
break; // should explicitly prefer default dialer (by packageName)?
|
||||
}
|
||||
}
|
||||
|
||||
if (found != null) {
|
||||
intent.setComponent(new ComponentName(found.applicationInfo.packageName, found.name));
|
||||
startActivity(intent);
|
||||
} else {
|
||||
LOG.error("onCreate() didn't find any dialer to launch");
|
||||
}
|
||||
|
||||
finish();
|
||||
}
|
||||
|
||||
}
|
@ -82,7 +82,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
@NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
|
||||
PermissionHelper.onRequestPermissionsResult(this, requestCode, permissions, grantResults,
|
||||
PermissionHelper.handlePermissionsResult(this, requestCode, permissions, grantResults,
|
||||
settings.getIncomingCallNotifications(), settings.getBlockCalls(),
|
||||
settings.getUseContacts());
|
||||
|
||||
|
@ -1,9 +1,12 @@
|
||||
package dummydomain.yetanothercallblocker;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
import android.telecom.TelecomManager;
|
||||
import android.text.TextUtils;
|
||||
import android.widget.Toast;
|
||||
|
||||
@ -20,9 +23,12 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public class PermissionHelper {
|
||||
|
||||
private static final int PERMISSION_REQUEST_CODE = 1;
|
||||
private static final int REQUEST_CODE_PERMISSIONS = 128;
|
||||
private static final int REQUEST_CODE_DEFAULT_DIALER = 129;
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(PermissionHelper.class);
|
||||
|
||||
@ -65,16 +71,16 @@ public class PermissionHelper {
|
||||
|
||||
if (!missingPermissions.isEmpty()) {
|
||||
ActivityCompat.requestPermissions(activity,
|
||||
missingPermissions.toArray(new String[0]), PERMISSION_REQUEST_CODE);
|
||||
missingPermissions.toArray(new String[0]), REQUEST_CODE_PERMISSIONS);
|
||||
}
|
||||
}
|
||||
|
||||
public static void onRequestPermissionsResult(@NonNull Context context, int requestCode,
|
||||
@NonNull String[] permissions,
|
||||
@NonNull int[] grantResults,
|
||||
boolean infoExpected, boolean blockingExpected,
|
||||
boolean contactsExpected) {
|
||||
if (requestCode != PERMISSION_REQUEST_CODE) return;
|
||||
public static void handlePermissionsResult(@NonNull Context context, int requestCode,
|
||||
@NonNull String[] permissions,
|
||||
@NonNull int[] grantResults,
|
||||
boolean infoExpected, boolean blockingExpected,
|
||||
boolean contactsExpected) {
|
||||
if (requestCode != REQUEST_CODE_PERMISSIONS) return;
|
||||
|
||||
boolean infoDenied = false;
|
||||
boolean blockingDenied = false;
|
||||
@ -139,4 +145,63 @@ public class PermissionHelper {
|
||||
== PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
public static void requestCallScreening(Activity activity) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
RoleManagerHelper.requestCallScreeningRole(activity);
|
||||
} else {
|
||||
setAsDefaultDialer(activity);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isCallScreeningHeld(Context context) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
if (RoleManagerHelper.hasCallScreeningRole(context)) return true;
|
||||
}
|
||||
|
||||
return isDefaultDialer(context);
|
||||
}
|
||||
|
||||
public static boolean handleCallScreeningResult(Context context,
|
||||
int requestCode, int resultCode) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
if (RoleManagerHelper.handleCallScreeningResult(context, requestCode, resultCode)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return handleDefaultDialerResult(context, requestCode, resultCode);
|
||||
}
|
||||
|
||||
public static boolean isDefaultDialer(Context context) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) return false;
|
||||
|
||||
TelecomManager telecomManager = requireNonNull(
|
||||
(TelecomManager) context.getSystemService(Context.TELECOM_SERVICE));
|
||||
|
||||
return BuildConfig.APPLICATION_ID.equals(telecomManager.getDefaultDialerPackage());
|
||||
}
|
||||
|
||||
public static void setAsDefaultDialer(Activity activity) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) return;
|
||||
if (isDefaultDialer(activity)) return;
|
||||
|
||||
Intent intent = new Intent(TelecomManager.ACTION_CHANGE_DEFAULT_DIALER);
|
||||
intent.putExtra(TelecomManager.EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME,
|
||||
BuildConfig.APPLICATION_ID);
|
||||
|
||||
activity.startActivityForResult(intent, REQUEST_CODE_DEFAULT_DIALER);
|
||||
}
|
||||
|
||||
public static boolean handleDefaultDialerResult(Context context,
|
||||
int requestCode, int resultCode) {
|
||||
if (requestCode != REQUEST_CODE_DEFAULT_DIALER) return false;
|
||||
|
||||
if (resultCode != Activity.RESULT_OK) {
|
||||
Toast.makeText(context, R.string.denied_default_dialer_message, Toast.LENGTH_LONG)
|
||||
.show();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,52 @@
|
||||
package dummydomain.yetanothercallblocker;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.role.RoleManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import static android.content.Context.ROLE_SERVICE;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.Q)
|
||||
public class RoleManagerHelper {
|
||||
|
||||
private static final int REQUEST_CODE_CALL_SCREENING = 130;
|
||||
|
||||
public static boolean hasCallScreeningRole(Context context) {
|
||||
return getRoleManager(context).isRoleHeld(RoleManager.ROLE_CALL_SCREENING);
|
||||
}
|
||||
|
||||
public static void requestCallScreeningRole(Activity activity) {
|
||||
if (hasCallScreeningRole(activity)) return;
|
||||
|
||||
Intent intent = getRoleManager(activity)
|
||||
.createRequestRoleIntent(RoleManager.ROLE_CALL_SCREENING);
|
||||
|
||||
activity.startActivityForResult(intent, REQUEST_CODE_CALL_SCREENING);
|
||||
}
|
||||
|
||||
public static boolean handleCallScreeningResult(Context context,
|
||||
int requestCode, int resultCode) {
|
||||
if (requestCode != REQUEST_CODE_CALL_SCREENING) return false;
|
||||
|
||||
if (resultCode != Activity.RESULT_OK) {
|
||||
Toast.makeText(context, R.string.denied_call_screening_role_message, Toast.LENGTH_LONG)
|
||||
.show();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static RoleManager getRoleManager(Context context) {
|
||||
@SuppressLint("WrongConstant")
|
||||
RoleManager roleManager = (RoleManager) context.getSystemService(ROLE_SERVICE);
|
||||
return requireNonNull(roleManager);
|
||||
}
|
||||
|
||||
}
|
@ -1,10 +1,15 @@
|
||||
package dummydomain.yetanothercallblocker;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
import androidx.preference.PreferenceGroup;
|
||||
@ -33,8 +38,34 @@ public class SettingsActivity extends AppCompatActivity {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
|
||||
@NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
|
||||
Settings settings = App.getSettings();
|
||||
|
||||
PermissionHelper.handlePermissionsResult(this, requestCode, permissions, grantResults,
|
||||
settings.getIncomingCallNotifications(), settings.getBlockCalls(),
|
||||
settings.getUseContacts());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
if (PermissionHelper.handleCallScreeningResult(this, requestCode, resultCode)) {
|
||||
for (Fragment fragment : getSupportFragmentManager().getFragments()) {
|
||||
if (fragment instanceof SettingsFragment) {
|
||||
((SettingsFragment) fragment).updateCallScreeningPreference();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class SettingsFragment extends PreferenceFragmentCompat {
|
||||
|
||||
private static final String PREF_USE_CALL_SCREENING_SERVICE = "useCallScreeningService";
|
||||
private static final String PREF_AUTO_UPDATE_ENABLED = "autoUpdateEnabled";
|
||||
private static final String PREF_CATEGORY_NOTIFICATIONS = "categoryNotifications";
|
||||
|
||||
@ -62,6 +93,24 @@ public class SettingsActivity extends AppCompatActivity {
|
||||
return true;
|
||||
});
|
||||
|
||||
SwitchPreferenceCompat callScreeningPref =
|
||||
requireNonNull(findPreference(PREF_USE_CALL_SCREENING_SERVICE));
|
||||
callScreeningPref.setChecked(PermissionHelper.isCallScreeningHeld(getActivity()));
|
||||
callScreeningPref.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
if (Boolean.TRUE.equals(newValue)) {
|
||||
PermissionHelper.requestCallScreening(getActivity());
|
||||
} else {
|
||||
Toast.makeText(getActivity(),
|
||||
R.string.use_call_screening_service_disable_message,
|
||||
Toast.LENGTH_LONG).show();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
|
||||
callScreeningPref.setVisible(false);
|
||||
}
|
||||
|
||||
SwitchPreferenceCompat nonPersistentAutoUpdatePref =
|
||||
requireNonNull(findPreference(PREF_AUTO_UPDATE_ENABLED));
|
||||
nonPersistentAutoUpdatePref.setChecked(updateScheduler.isAutoUpdateScheduled());
|
||||
@ -103,5 +152,11 @@ public class SettingsActivity extends AppCompatActivity {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateCallScreeningPreference() {
|
||||
SwitchPreferenceCompat callScreeningPref =
|
||||
requireNonNull(findPreference(PREF_USE_CALL_SCREENING_SERVICE));
|
||||
callScreeningPref.setChecked(PermissionHelper.isCallScreeningHeld(getActivity()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,8 +13,12 @@ public class CallLogItem {
|
||||
switch (type) {
|
||||
case CallLog.Calls.INCOMING_TYPE: return INCOMING;
|
||||
case CallLog.Calls.OUTGOING_TYPE: return OUTGOING;
|
||||
case CallLog.Calls.MISSED_TYPE: return MISSED;
|
||||
case CallLog.Calls.REJECTED_TYPE: return REJECTED;
|
||||
case CallLog.Calls.MISSED_TYPE:
|
||||
case CallLog.Calls.VOICEMAIL_TYPE:
|
||||
return MISSED;
|
||||
case CallLog.Calls.REJECTED_TYPE:
|
||||
case CallLog.Calls.BLOCKED_TYPE:
|
||||
return REJECTED;
|
||||
default: return OTHER;
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,9 @@
|
||||
<string name="sia_category_nonprofit">Некоммерческая орг-я</string>
|
||||
<string name="block_calls">Блокир-ть нежелат. вызовы</string>
|
||||
<string name="block_calls_summary">Автоматически сбрасывать звонки c номеров с отрицательным рейтингом</string>
|
||||
<string name="use_call_screening_service">Продвинутый режим блокирования вызовов</string>
|
||||
<string name="use_call_screening_service_summary">Позволяет блокировать вызовы до того, как телефон зазвонит. Это требует назначить приложение \"приложением для звонков\" (на Android 7–9) или \"приложением для АОН и защиты от спама\" (на Android 10+)</string>
|
||||
<string name="use_call_screening_service_disable_message">Выберите другое приложение для звонков или защиты от спама в меню Настройки - Приложения - Приложения по умолчанию</string>
|
||||
<string name="auto_updates">Авто-обновл. базы номеров</string>
|
||||
<string name="auto_updates_summary">Получать ежедневные обновления базы (загружаются только изменения, поэтому расход трафика небольшой)</string>
|
||||
<string name="open_debug_activity">Работа с базой номеров</string>
|
||||
@ -53,6 +56,8 @@
|
||||
<string name="feature_info">уведомления</string>
|
||||
<string name="feature_call_blocking">блокир-е вызовов</string>
|
||||
<string name="feature_contacts">имена контактов</string>
|
||||
<string name="denied_default_dialer_message">Продвинутый режим блокирования не сможет работать, т.к. приложение не назначено \"приложением для звонков\"</string>
|
||||
<string name="denied_call_screening_role_message">Продвинутый режим блокирования не сможет работать, т.к. приложение не назначено \"приложением для АОН и защиты от спама\"</string>
|
||||
<string name="no_main_db_title">Загрузить базу номеров</string>
|
||||
<string name="no_main_db_text">База номеров отсутствует. Для полноценной работы приложения требуется загрузка базы номеров (около 25 МБ трафика).</string>
|
||||
<string name="download_main_db">Загрузить базу номеров</string>
|
||||
@ -73,6 +78,7 @@
|
||||
<string name="open_settings_activity">Настройки</string>
|
||||
<string name="title_settings_activity">Настройки</string>
|
||||
<string name="settings_category_main">Основные</string>
|
||||
<string name="settings_category_call_blocking">Блокирование вызовов</string>
|
||||
<string name="settings_category_notifications_incoming_calls">Уведомления на входящие</string>
|
||||
<string name="show_notifications_for_known_callers">Уведомления для известных звонящих</string>
|
||||
<string name="show_notifications_for_known_callers_summary">Показывать уведомления для известных звонящих (номеров из телефонной книги)</string>
|
||||
|
@ -56,6 +56,8 @@
|
||||
<string name="feature_info">notifications</string>
|
||||
<string name="feature_call_blocking">call blocking</string>
|
||||
<string name="feature_contacts">using contacts</string>
|
||||
<string name="denied_default_dialer_message">Advanced call blocking won\'t work due to the app not being set as the \"Phone app\"</string>
|
||||
<string name="denied_call_screening_role_message">Advanced call blocking won\'t work due to the app not being set as the \"Caller ID app\"</string>
|
||||
|
||||
<string name="call_log_permission_message">Grant \"Phone\" permission to see recent calls</string>
|
||||
|
||||
@ -77,6 +79,7 @@
|
||||
<string name="open_settings_activity">Settings</string>
|
||||
<string name="title_settings_activity">Settings</string>
|
||||
<string name="settings_category_main">Main</string>
|
||||
<string name="settings_category_call_blocking">Call blocking</string>
|
||||
<string name="settings_category_notifications_incoming_calls">Incoming calls notifications</string>
|
||||
<string name="show_notifications_for_known_callers">Notifications for known callers</string>
|
||||
<string name="show_notifications_for_known_callers_summary">Display notifications for known callers (numbers in Contacts)</string>
|
||||
@ -87,6 +90,9 @@
|
||||
<string name="incoming_call_notifications_summary">Displays a notification with phone number summary (rating, reviews count, category) during incoming calls</string>
|
||||
<string name="block_calls">Block unwanted calls</string>
|
||||
<string name="block_calls_summary">Automatically blocks calls with negative rating</string>
|
||||
<string name="use_call_screening_service">Advanced call blocking mode</string>
|
||||
<string name="use_call_screening_service_summary">Allows to block calls before the phone starts to ring. Requires the app to be set as the \"Phone app\" (Android 7–9) or as the \"Caller ID app\" (Android 10+)</string>
|
||||
<string name="use_call_screening_service_disable_message">Select different \"Phone app\" or \"Caller ID app\" in Settings - Apps - Default apps</string>
|
||||
<string name="auto_updates">Auto-update database</string>
|
||||
<string name="auto_updates_summary">Automatically receive daily DB updates (these are incremental/delta updates, so they consume very little traffic)</string>
|
||||
<string name="use_contacts">Use contacts</string>
|
||||
|
@ -1,5 +1,4 @@
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<PreferenceCategory app:title="@string/settings_category_main">
|
||||
<SwitchPreferenceCompat
|
||||
@ -7,10 +6,6 @@
|
||||
app:key="incomingCallNotifications"
|
||||
app:summary="@string/incoming_call_notifications_summary"
|
||||
app:title="@string/incoming_call_notifications" />
|
||||
<SwitchPreferenceCompat
|
||||
app:key="blockCalls"
|
||||
app:summary="@string/block_calls_summary"
|
||||
app:title="@string/block_calls" />
|
||||
<SwitchPreferenceCompat
|
||||
app:key="autoUpdateEnabled"
|
||||
app:persistent="false"
|
||||
@ -22,6 +17,18 @@
|
||||
app:title="@string/use_contacts" />
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory app:title="@string/settings_category_call_blocking">
|
||||
<SwitchPreferenceCompat
|
||||
app:key="blockCalls"
|
||||
app:summary="@string/block_calls_summary"
|
||||
app:title="@string/block_calls" />
|
||||
<SwitchPreferenceCompat
|
||||
app:key="useCallScreeningService"
|
||||
app:persistent="false"
|
||||
app:summary="@string/use_call_screening_service_summary"
|
||||
app:title="@string/use_call_screening_service" />
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
app:key="categoryNotifications"
|
||||
app:title="@string/settings_category_notifications_incoming_calls">
|
||||
|
Loading…
x
Reference in New Issue
Block a user