### Handling Permission Denial Exception Source: https://github.com/getactivity/xxpermissions/blob/master/Details-zh.md This example shows a `SecurityException` that can occur due to permission denial when starting an Intent. This highlights that even if an Intent exists, it might not be launchable due to security restrictions. ```text java.lang.SecurityException: Permission Denial: starting Intent { act=android.settings.MANAGE_UNKNOWN_APP_SOURCES (has data) cmp=xxxx/xxx } ``` -------------------------------- ### Launch APK Installation Intent Source: https://github.com/getactivity/xxpermissions/blob/master/HelpDoc-zh.md This code snippet demonstrates how to launch an APK installation intent. It includes logic for handling Android N+ file URI permissions and is crucial for understanding the behavior differences across various Android versions and manufacturers regarding installation prompts. ```Java Intent intent = new Intent(Intent.ACTION_VIEW); Uri uri; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { uri = FileProvider.getUriForFile(context, context.getPackageName() + ".provider", file); } else { uri = Uri.fromFile(file); } intent.setDataAndType(uri, "application/vnd.android.package-archive"); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); context.startActivity(intent); ``` -------------------------------- ### Request Install Packages Permission Source: https://context7.com/getactivity/xxpermissions/llms.txt Request permission to install unknown apps. The callback is invoked after the user grants or denies the permission. ```java XXPermissions.with(this) .permission(PermissionLists.getRequestInstallPackagesPermission()) .request((grantedList, deniedList) -> { if (deniedList.isEmpty()) { installApk(apkFile); } }); ``` -------------------------------- ### XXPermissions Start Permission Activity Source: https://github.com/getactivity/xxpermissions/blob/master/Details-zh.md This method from the XXPermissions framework provides a robust solution for starting permission-related activities. It internally handles multiple Intent fallbacks to ensure successful navigation even when specific intents are unavailable or restricted. ```java XXPermissions.startPermissionActivity(context); ``` -------------------------------- ### Implement Custom Permission Interceptor Source: https://context7.com/getactivity/xxpermissions/llms.txt Implement OnPermissionInterceptor to execute custom logic before and after permission requests, such as showing a permission explanation dialog. Use XXPermissions.setPermissionInterceptor() for global setup or XXPermissions.with().interceptor() for local setup. ```java // 自定义拦截器 public class MyPermissionInterceptor implements OnPermissionInterceptor { @Override public void onRequestPermissionStart(@NonNull Activity activity, @NonNull List requestList, @NonNull PermissionFragmentFactory fragmentFactory, @NonNull OnPermissionDescription permissionDescription, @Nullable OnPermissionCallback callback) { // 在申请权限前显示说明对话框 new AlertDialog.Builder(activity) .setTitle("权限申请") .setMessage("我们需要以下权限来提供完整功能") .setPositiveButton("确定", (dialog, which) -> { // 用户同意后继续申请 dispatchPermissionRequest(activity, requestList, fragmentFactory, permissionDescription, callback); }) .setNegativeButton("取消", null) .show(); } } ``` ```java // 全局设置拦截器 XXPermissions.setPermissionInterceptor(MyPermissionInterceptor.class); ``` ```java // 局部设置拦截器 XXPermissions.with(this) .permission(PermissionLists.getCameraPermission()) .interceptor(new MyPermissionInterceptor()) .request((grantedList, deniedList) -> { // 处理结果 }); ``` -------------------------------- ### Local Permission Description and Interceptor Setup Source: https://github.com/getactivity/xxpermissions/blob/master/HelpDoc-zh.md Configure permission descriptions and interceptors for specific permission requests. This is useful when you need different behaviors for different permission groups. ```java XXPermissions.with(this) .permission(PermissionLists.getXxx()) // 设置权限说明(局部设置) .description(new PermissionDescription()) // 设置权限请求拦截器(局部设置) .interceptor(new PermissionInterceptor()) .request(new OnPermissionCallback() { ...... }); ``` -------------------------------- ### Global Permission Description and Interceptor Setup Source: https://github.com/getactivity/xxpermissions/blob/master/HelpDoc-zh.md Set permission descriptions and interceptors globally for all permission requests in the application. This simplifies configuration by applying the same logic across the entire app. ```java public class XxxApplication extends Application { @Override public void onCreate() { super.onCreate(); // 设置权限说明(全局设置) XXPermissions.setPermissionDescription(PermissionDescription.class); // 设置权限请求拦截器(全局设置) XXPermissions.setPermissionInterceptor(PermissionInterceptor.class); } } ``` -------------------------------- ### Handling Intent Not Found Exception Source: https://github.com/getactivity/xxpermissions/blob/master/Details-zh.md This example illustrates the `ActivityNotFoundException` that can occur when an Intent action is not handled by any activity on the device. This is a common issue with certain system settings intents. ```text android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.settings.APPLICATION_DETAILS_SETTINGS dat=Package Name:com.xxx.xxx } ``` -------------------------------- ### Exception for ActivityNotFoundException Source: https://github.com/getactivity/xxpermissions/blob/master/Details-zh.md This exception indicates that no Activity was found to handle the `android.content.pm.action.REQUEST_PERMISSIONS` intent, often due to system package installer modifications or removal. ```text android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.content.pm.action.REQUEST_PERMISSIONS pkg=com.android.packageinstaller (has extras) } ``` -------------------------------- ### Request Accessibility Service Permission Source: https://context7.com/getactivity/xxpermissions/llms.txt Request permission to bind an AccessibilityService. The framework will guide the user to the accessibility settings page. ```java XXPermissions.with(this) .permission(PermissionLists.getBindAccessibilityServicePermission(MyAccessibilityService.class)) .request((grantedList, deniedList) -> { if (deniedList.isEmpty()) { // 无障碍服务已开启 Log.i("Permission", "Accessibility service enabled"); } }); ``` -------------------------------- ### Jump to Permission Settings Page Source: https://context7.com/getactivity/xxpermissions/llms.txt Provides methods to navigate to the system's permission settings page, with options to specify permissions and listen for return results. ```java // 方式一:直接跳转到应用权限设置页 XXPermissions.startPermissionActivity(context); // 方式二:跳转并指定需要设置的权限 XXPermissions.startPermissionActivity(context, PermissionLists.getCameraPermission()); // 方式三:跳转并监听返回结果 XXPermissions.startPermissionActivity(activity, Arrays.asList(PermissionLists.getCameraPermission()), (grantedList, deniedList) -> { if (deniedList.isEmpty()) { // 用户在设置页授予了权限 openCamera(); } }); ``` -------------------------------- ### Request Device Manager Permission Source: https://context7.com/getactivity/xxpermissions/llms.txt Request permission to activate the device manager. The framework will display the system's device manager activation page. ```java XXPermissions.with(this) .permission(PermissionLists.getBindDeviceAdminPermission( MyDeviceAdminReceiver.class, "需要设备管理器权限来远程锁定和擦除设备" )) .request((grantedList, deniedList) -> { if (deniedList.isEmpty()) { // 设备管理器已激活 enableDeviceAdmin(); } }); ``` -------------------------------- ### Re-requesting Permissions After Denial (Manual Implementation) Source: https://github.com/getactivity/xxpermissions/blob/master/HelpDoc-zh.md Implement a custom logic to re-request permissions if they are denied, including a check for permanent denial. If permanently denied, it prompts the user to go to the system settings to grant the permission. ```java public class PermissionActivity extends AppCompatActivity implements OnPermissionCallback { @Override public void onClick(View view) { requestCameraPermission(); } private void requestCameraPermission() { XXPermissions.with(this) .permission(PermissionLists.getCameraPermission()) .request(this); } @Override public void onResult(@NonNull List grantedList, @NonNull List deniedList) { boolean allGranted = deniedList.isEmpty(); if (!allGranted) { boolean doNotAskAgain = XXPermissions.isDoNotAskAgainPermissions(activity, deniedList); if (doNotAskAgain) { toast("被永久拒绝授权,请手动授予拍照权限""); // 如果是被永久拒绝就跳转到应用权限系统设置页面 XXPermissions.startPermissionActivity(activity, deniedList); } else { requestCameraPermission(); } return; } toast("获取拍照权限成功"); } @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode != XXPermissions.REQUEST_CODE) { return; } toast("检测到你刚刚从权限设置界面返回回来"); } } ``` -------------------------------- ### Use Older XXPermissions Versions for Support Library Source: https://github.com/getactivity/xxpermissions/blob/master/README-en.md Optionally, use older versions of XXPermissions and DeviceCompat if your project still uses the Support Library and cannot migrate to AndroidX immediately. This is a temporary measure. ```groovy dependencies { // Device compatibility framework:https://github.com/getActivity/DeviceCompat implementation 'com.github.getActivity:DeviceCompat:2.3' // Permission request framework:https://github.com/getActivity/XXPermissions implementation 'com.github.getActivity:XXPermissions:26.8' } ``` -------------------------------- ### Add XXPermissions Dependencies Source: https://github.com/getactivity/xxpermissions/blob/master/README-en.md Include the XXPermissions and DeviceCompat libraries in your app module's build.gradle file. Ensure JDK 1.8 is configured for compatibility. ```groovy android { // Support JDK 1.8 compileOptions { targetCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8 } } dependencies { // Device compatibility framework:https://github.com/getActivity/DeviceCompat implementation 'com.github.getActivity:DeviceCompat:2.6' // Permission request framework:https://github.com/getActivity/XXPermissions implementation 'com.github.getActivity:XXPermissions:28.2' } ``` -------------------------------- ### XXPermissions Dependency (Support Library) Source: https://github.com/getactivity/xxpermissions/blob/master/README.md Use these dependencies if your project is still in the Support Library phase and cannot migrate to AndroidX. This is a temporary solution. ```groovy dependencies { // 设备兼容框架:https://github.com/getActivity/DeviceCompat implementation 'com.github.getActivity:DeviceCompat:2.3' // 权限请求框架:https://github.com/getActivity/XXPermissions implementation 'com.github.getActivity:XXPermissions:26.8' } ``` -------------------------------- ### Implement Permission Interceptor for 48-Hour Rule Source: https://github.com/getactivity/xxpermissions/blob/master/HelpDoc-zh.md Override onRequestPermissionStart to check the last permission request time stored in SharedPreferences. If within 48 hours, it directly calls the permission denied callback; otherwise, it proceeds with the permission request. ```java public final class PermissionInterceptor implements OnPermissionInterceptor { private static final String SP_NAME_PERMISSION_REQUEST_TIME_RECORD = "permission_request_time_record"; @Override public void onRequestPermissionStart(@NonNull Activity activity, @NonNull List requestList, @NonNull PermissionFragmentFactory fragmentFactory, @NonNull OnPermissionDescription permissionDescription, @Nullable OnPermissionCallback callback) { SharedPreferences sharedPreferences = activity.getSharedPreferences(SP_NAME_PERMISSION_REQUEST_TIME_RECORD, Context.MODE_PRIVATE); String permissionKey = String.valueOf(requestList); long lastRequestPermissionTime = sharedPreferences.getLong(permissionKey, 0); if (System.currentTimeMillis() - lastRequestPermissionTime <= 1000 * 60 * 60 * 24 * 2) { List deniedList = XXPermissions.getDeniedPermissions(activity, requestList); List grantedList = new ArrayList<>(requestList); grantedList.removeAll(deniedList); onRequestPermissionEnd(activity, true, requestList, grantedList, deniedList, callback); return; } sharedPreferences.edit().putLong(permissionKey, System.currentTimeMillis()).apply(); // 如果之前没有申请过权限,或者距离上次申请已经超过了 48 个小时,则进行申请权限 dispatchPermissionRequest(activity, requestList, fragmentFactory, permissionDescription, callback); } } ``` -------------------------------- ### Add XXPermissions Dependency Source: https://github.com/getactivity/xxpermissions/blob/master/README.md Add the XXPermissions and DeviceCompat libraries to your app's build.gradle file. Ensure your project supports JDK 1.8 or higher. ```groovy android { // 支持 JDK 1.8 及以上 compileOptions { targetCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8 } } dependencies { // 设备兼容框架:https://github.com/getActivity/DeviceCompat implementation 'com.github.getActivity:DeviceCompat:2.6' // 权限请求框架:https://github.com/getActivity/XXPermissions implementation 'com.github.getActivity:XXPermissions:28.2' } ``` -------------------------------- ### Jump to Application Details Settings Source: https://github.com/getactivity/xxpermissions/blob/master/Details-zh.md This code snippet demonstrates a basic attempt to jump to the application details settings page. It is prone to `ActivityNotFoundException` on devices where this intent is not supported. ```java Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.setData("package:" + getPackageName()); startActivityForResult(intent, 1024); ``` -------------------------------- ### Request Multiple Permissions in Kotlin Source: https://github.com/getactivity/xxpermissions/blob/master/README.md This Kotlin snippet shows how to request multiple permissions using XXPermissions. It includes logic for handling granted and denied permissions, and checking for the 'do not ask again' option. Make sure XXPermissions and PermissionLists are properly imported. ```kotlin XXPermissions.with(this) // 申请多个权限 .permission(PermissionLists.getRecordAudioPermission()) .permission(PermissionLists.getCameraPermission()) // 设置不触发错误检测机制(局部设置) //.unchecked() .request { grantedList, deniedList -> val allGranted = deniedList.isEmpty() if (!allGranted) { // 判断请求失败的权限是否被用户勾选了不再询问的选项 val doNotAskAgain = XXPermissions.isDoNotAskAgainPermissions(activity, deniedList) // 在这里处理权限请求失败的逻辑 // ...... return@request } // 在这里处理权限请求成功的逻辑 // ...... } ``` -------------------------------- ### Configure JitPack Repository (Gradle >= 7.0) Source: https://github.com/getactivity/xxpermissions/blob/master/README-en.md Add the JitPack remote repository to your project's settings.gradle file if using Gradle version 7.0 or above. ```groovy dependencyResolutionManagement { repositories { // JitPack remote repository:https://jitpack.io maven { url 'https://jitpack.io' } } } ``` -------------------------------- ### Add JitPack Repository (Gradle < 7.0) Source: https://github.com/getactivity/xxpermissions/blob/master/README.md Configure your project's build.gradle file to include the JitPack remote repository if your Gradle version is below 7.0. ```groovy allprojects { repositories { // JitPack 远程仓库:https://jitpack.io maven { url 'https://jitpack.io' } } } ``` -------------------------------- ### Request Floating Window Permission Source: https://context7.com/getactivity/xxpermissions/llms.txt Use this to request the floating window permission. The callback is invoked after the user grants or denies the permission. ```java XXPermissions.with(this) .permission(PermissionLists.getSystemAlertWindowPermission()) .request((grantedList, deniedList) -> { if (deniedList.isEmpty()) { showFloatingWindow(); } }); ``` -------------------------------- ### Configure JitPack Repository (Gradle < 7.0) Source: https://github.com/getactivity/xxpermissions/blob/master/README-en.md Add the JitPack remote repository to your project's root Gradle configuration if using Gradle version 7.0 or below. ```groovy allprojects { repositories { // JitPack remote repository:https://jitpack.io maven { url 'https://jitpack.io' } } } ``` -------------------------------- ### Request Ignore Battery Optimizations Permission Source: https://context7.com/getactivity/xxpermissions/llms.txt Request permission to ignore battery optimizations. The callback is invoked after the user grants or denies the permission. ```java XXPermissions.with(this) .permission(PermissionLists.getRequestIgnoreBatteryOptimizationsPermission()) .request((grantedList, deniedList) -> { if (deniedList.isEmpty()) { startBackgroundService(); } }); ``` -------------------------------- ### Kotlin Extension for Permission Requests Source: https://context7.com/getactivity/xxpermissions/llms.txt Utilize Kotlin lambda expressions for a more concise way to handle permission request callbacks. This simplifies the code for requesting multiple permissions and processing the results. ```kotlin XXPermissions.with(this) .permission(PermissionLists.getCameraPermission()) .permission(PermissionLists.getRecordAudioPermission()) .request { val allGranted = deniedList.isEmpty() if (!allGranted) { val doNotAskAgain = XXPermissions.isDoNotAskAgainPermissions(activity, deniedList) if (doNotAskAgain) { // 权限被永久拒绝,引导用户去设置页 XXPermissions.startPermissionActivity(activity, deniedList) } return@request } // 权限申请成功 startCameraAndRecording() } ``` -------------------------------- ### Configure Scoped Storage in AndroidManifest.xml Source: https://github.com/getactivity/xxpermissions/blob/master/README.md Add this meta-data tag to your AndroidManifest.xml if your project has adapted to the Android 10 Scoped Storage feature. This informs XXPermissions about your project's storage handling. ```xml ``` -------------------------------- ### Handling Permanently Denied Permissions Source: https://github.com/getactivity/xxpermissions/blob/master/HelpDoc-zh.md Check if specific permissions have been permanently denied by the user, indicated by the 'do not ask again' option being selected. This allows for tailored user guidance, such as directing them to the app's settings. ```java XXPermissions.with(this) .permission(PermissionLists.getRecordAudioPermission()) .permission(PermissionLists.getReadCalendarPermission()) .permission(PermissionLists.getWriteCalendarPermission()) .request(new OnPermissionCallback() { @Override public void onResult(@NonNull List grantedList, @NonNull List deniedList) { boolean allGranted = deniedList.isEmpty(); if (!allGranted) { IPermission recordAudioPermission = PermissionLists.getRecordAudioPermission(); if (deniedList.contains(recordAudioPermission) && XXPermissions.isDoNotAskAgainPermission(activity, recordAudioPermission)) { toast("录音权限请求被拒绝了,并且用户勾选了不再询问"); } return; } toast("获取录音和日历权限成功"); } }); ``` -------------------------------- ### Enable Permission Check Mode Source: https://context7.com/getactivity/xxpermissions/llms.txt Enable check mode in the Application class to automatically verify permission configurations during development. This helps catch errors early. It's recommended to enable this only in Debug mode. ```java // 在 Application 中设置 public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); // 建议只在 Debug 模式下开启 XXPermissions.setCheckMode(BuildConfig.DEBUG); } } ``` -------------------------------- ### Android 11 Storage Permission Adaptation Source: https://github.com/getactivity/xxpermissions/blob/master/HelpDoc-zh.md To adapt for Android 11 scoped storage, update `targetSdkVersion` to 30, declare `MANAGE_EXTERNAL_STORAGE` in the manifest, and optionally `requestLegacyExternalStorage` for compatibility. Use `XXPermissions.with().permission(PermissionLists.getManageExternalStoragePermission()).request()` for requesting the permission. ```groovy android defaultConfig { targetSdkVersion 30 } } ``` ```xml ``` ```xml ``` ```xml ``` ```java XXPermissions.with(MainActivity.this) // 适配 Android 11 分区存储这样写 //.permission(PermissionLists.getReadExternalStoragePermission()) //.permission(PermissionLists.getWriteExternalStoragePermission()) // 不适配 Android 11 分区存储这样写 .permission(PermissionLists.getManageExternalStoragePermission()) .request(new OnPermissionCallback() { ...... }); ``` -------------------------------- ### Request Multiple Permissions in Java Source: https://github.com/getactivity/xxpermissions/blob/master/README.md Use this snippet to request multiple permissions in your Android application using Java. It handles both granted and denied permissions, including checking if the user selected 'do not ask again'. Ensure XXPermissions and PermissionLists are correctly imported. ```java XXPermissions.with(this) // 申请多个权限 .permission(PermissionLists.getRecordAudioPermission()) .permission(PermissionLists.getCameraPermission()) // 设置不触发错误检测机制(局部设置) //.unchecked() .request((grantedList, deniedList) -> { boolean allGranted = deniedList.isEmpty(); if (!allGranted) { // 判断请求失败的权限是否被用户勾选了不再询问的选项 boolean doNotAskAgain = XXPermissions.isDoNotAskAgainPermissions(activity, deniedList); // 在这里处理权限请求失败的逻辑 // ...... return; } // 在这里处理权限请求成功的逻辑 // ...... }); ``` -------------------------------- ### Check if Permission is Permanently Denied Source: https://context7.com/getactivity/xxpermissions/llms.txt Determine if the user has selected 'Do not ask again' for a permission. This is typically checked in the permission callback. ```java XXPermissions.with(this) .permission(PermissionLists.getCameraPermission()) .request((grantedList, deniedList) -> { if (!deniedList.isEmpty()) { // 检查是否被永久拒绝 boolean doNotAskAgain = XXPermissions.isDoNotAskAgainPermissions(activity, deniedList); if (doNotAskAgain) { // 引导用户到设置页手动开启权限 new AlertDialog.Builder(activity) .setMessage("相机权限已被永久拒绝,请到设置页手动开启") .setPositiveButton("去设置", (dialog, which) -> { XXPermissions.startPermissionActivity(activity, deniedList); }) .setNegativeButton("取消", null) .show(); } } }); ``` -------------------------------- ### Handle potential null or empty arrays in onRequestPermissionsResult Source: https://github.com/getactivity/xxpermissions/blob/master/Details-zh.md Safeguard against `NullPointerException` or `ArrayIndexOutOfBoundsException` in `onRequestPermissionsResult` by checking if `permissions` or `grantResults` are empty or have mismatched lengths before accessing their elements. Consider using `checkSelfPermission` as a more reliable alternative. ```java public final class XxxActivity extends AppCompatActivity { @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (permissions.length == 0 || grantResults.length == 0) { return; } if (permissions[0].equals(Manifest.permission.CAMERA) && grantResults[0] == PackageManager.PERMISSION_GRANTED) { System.out.println("获取相机权限成功"); } else { System.out.println("获取相机权限失败"); } } } ``` -------------------------------- ### Prevent ActivityNotFoundException with try-catch Source: https://github.com/getactivity/xxpermissions/blob/master/Details-zh.md Use a try-catch block around `activity.requestPermissions` to prevent crashes caused by `ActivityNotFoundException`, which can occur even on Android 6.0+ due to system modifications. ```java activity.requestPermissions(new String[]{Manifest.permission.CAMERA}, 1024); ``` -------------------------------- ### Check Permission Status Source: https://context7.com/getactivity/xxpermissions/llms.txt Check the granted status of permissions without initiating a request. This can be used for single or multiple permissions. ```java // 检查单个权限 boolean cameraGranted = XXPermissions.isGrantedPermission(context, PermissionLists.getCameraPermission()); // 检查多个权限 List permissions = Arrays.asList( PermissionLists.getCameraPermission(), PermissionLists.getRecordAudioPermission() ); boolean allGranted = XXPermissions.isGrantedPermissions(context, permissions); // 获取已授予的权限列表 List grantedPermissions = XXPermissions.getGrantedPermissions(context, permissions); // 获取被拒绝的权限列表 List deniedPermissions = XXPermissions.getDeniedPermissions(context, permissions); ``` -------------------------------- ### Request Health Data Permissions Source: https://context7.com/getactivity/xxpermissions/llms.txt Request permissions to read and write health data from Health Connect. This is available on Android 14+. ```java XXPermissions.with(this) .permission(PermissionLists.getReadSleepPermission()) .permission(PermissionLists.getReadHeartRatePermission()) .permission(PermissionLists.getWriteHeartRatePermission()) .permission(PermissionLists.getReadExercisePermission()) .request((grantedList, deniedList) -> { if (deniedList.isEmpty()) { // 读取健康数据 readHealthData(); } }); ``` -------------------------------- ### Disable Check Mode for Single Request Source: https://context7.com/getactivity/xxpermissions/llms.txt Optionally disable the check mode for a single permission request using the .unchecked() method. This is generally not recommended as it bypasses error checking for that specific request. ```java // 单次请求禁用检测(不推荐) XXPermissions.with(this) .permission(PermissionLists.getCameraPermission()) .unchecked() .request((grantedList, deniedList) -> { // 处理结果 }); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.