我使用它是Settings.ACTION_APPLICATION_DETAILS_SETTINGS为了在用户未故意授予权限时发出请求。
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getActivity().getPackageName(), null);
intent.setData(uri);
getActivity().startActivity(intent);
Run Code Online (Sandbox Code Playgroud)
该代码仅在 Android 13 下运行良好。如果我在 Android 13 中运行此代码,则会发生异常。
"Bad call made by uid 1000. Package "package name" does not belong to uid -1.
noteOperation
java.lang.SecurityException: Specified package "package name" under uid -1 but it is not
at com.android.server.appop.AppOpsService.verifyAndGetBypass(AppOpsService.java:4858)
at com.android.server.appop.AppOpsService.noteOperationUnchecked(AppOpsService.java:3586)
at com.android.server.appop.AppOpsService.noteOperationImpl(AppOpsService.java:3574)
at com.android.server.appop.AppOpsService.-$$Nest$mnoteOperationImpl(Unknown Source:0)
at com.android.server.appop.AppOpsService$CheckOpsDelegateDispatcher.lambda$noteOperation$4(AppOpsService.java:7928)
at com.android.server.appop.AppOpsService$CheckOpsDelegateDispatcher.$r8$lambda$oOwUoG55BBmJ6yiwhp3OAq3tQ30(Unknown Source:0)
at com.android.server.appop.AppOpsService$CheckOpsDelegateDispatcher$$ExternalSyntheticLambda4.apply(Unknown Source:32)
at com.android.server.policy.AppOpsPolicy.noteOperation(AppOpsPolicy.java:225)
at com.android.server.appop.AppOpsService$CheckOpsDelegateDispatcher.noteOperation(AppOpsService.java:7926)
at com.android.server.appop.AppOpsService.noteOperation(AppOpsService.java:3558)
at com.android.internal.app.IAppOpsService$Stub.onTransact(IAppOpsService.java:486)
at android.os.Binder.execTransactInternal(Binder.java:1316)
at …Run Code Online (Sandbox Code Playgroud) 当我们平时使用 Room 时,我们使用 Kotlin Coroutine 并创建一个 DAO 来访问 Room 并获取结果。大多数函数通常suspend在函数开头有修饰符 butLiveData和Flow。例如,让我们看一下下面的这两段代码。
@Query("SELECT * FROM MockTable")
suspend fun allMockDataWithSuspend(): List<MockData>
@Query("SELECT * FROM MockTable")
fun allMockData(): Flow<List<MockData>> // or LiveData<List<MockData>>
Run Code Online (Sandbox Code Playgroud)
当我们使用suspend修饰符时,我们需要在协程范围内调用该函数,因为该函数具有 suspend 修饰符。LiveData但是当函数的结果是或者Flow即使是 I/O 访问时,我们不需要在协程中调用该函数。
这怎么可能?
android android-room android-livedata kotlin-coroutines kotlin-flow
我正在制作一个 APK 安装应用程序,并且经历了很多。特别是版本控制。为此,我查阅了一些帖子和 StackOverFlow。但现在所有的帖子让我更加困惑。那么,什么是正确的方法呢?
首先,请检查我下面关于每个版本安装的代码。让我们谈谈什么是正确的方法。
KitKat(API 19)、棒棒糖(API 21)、MashMellow(API 23)
fun installApkBelowNougat(apkFile: File) {
val apkUri = Uri.fromFile(apkFile)
val intent = Intent(Intent.ACTION_VIEW).apply {
setDataAndType(apkUri, "application/vnd.android.package-archive")
flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,所有解决方案都是相同的,我们必须使用Uri.fromFile(file)来获得Uri.
牛轧糖(API 24)
fun installApkInNougat(apkFile: File) {
val apkUri = FileProvider.getUriForFile(applicationContext, applicationContext.packageName + ".fileProvider", apkFile)
val intent = Intent(Intent.ACTION_VIEW).apply {
setDataAndType(apkUri, "application/vnd.android.package-archive")
flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我们就不能再使用了Uri.fromFile(file)。因此,我们必须使用FileProvider“Nougat”来代替它。并且我们还必须<proivder/>在AndroidManifest.xml中这样写。
...
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS" …Run Code Online (Sandbox Code Playgroud) 我正在PendingIntent处理notification. 在我的项目中,我一直PendingIntent.FLAG_UPDATE_CURRENT在一些代码中使用。它的定义如下。
标志指示如果所描述的 PendingIntent 已经存在,则保留它,但用这个新 Intent 中的内容替换其额外数据。用于 getActivity(Context, int, Intent, int)、getBroadcast(Context, int, Intent, int) 和 getService(Context, int, Intent, int)。
如果您正在创建仅额外内容发生变化的意图,并且不关心接收到您之前的 PendingIntent 的任何实体将能够使用新的额外内容启动它,即使它们没有明确提供给它,则可以使用此方法。
即使设置了 FLAG_IMMUTABLE,FLAG_UPDATE_CURRENT 仍然有效 - PendingIntent 的创建者始终可以更新 PendingIntent 本身。IMMUTABLE 标志仅限制 send() 调用者更改 send() 发送的意图语义的能力。
但我必须选择FLAG_IMMUTABLE还是FLAG_MUTABLE因为Android12。就我而言,我不需要使用PendingIntent.FLAG_MUTABLE. 它的定义如下。
指示创建的 PendingIntent 应该是不可变的标志。这意味着传递给发送方法以填充此意图的未填充属性的附加意图参数将被忽略。
FLAG_IMMUTABLE 仅限制 send() 调用者更改 send() 发送的意图语义的能力。PendingIntent 的创建者始终可以通过 FLAG_UPDATE_CURRENT 更新 PendingIntent 本身。
正如你所看到的,他们说“即使设置了 FLAG_IMMUTABLE,FLAG_UPDATE_CURRENT 仍然有效...”和“PendingIntent 的创建者始终可以通过 FLAG_UPDATE_CURRENT 更新 PendingIntent 本身。”
那么,我想知道的是,它可以在任何Android版本中FLAG_IMMUTABLE完美替代吗?FLAG_UPDATE_CURRENT
例如
PendingIntent.getActivity(context, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT); …Run Code Online (Sandbox Code Playgroud) 当我们不想维护SharedPreferences或任何备份文件时,我们可以直接设置android:allowBackup="false"为AndroidManifest.xml.
但android:allowBackup="false"在 Android12 中已弃用。尽管它已被弃用,我们仍然可以继续使用它cloud-based backup。例如,如果我们正在使用SharedPreferences,则删除我们的应用程序并重新安装后,它们SharedPreferences就会消失。您可以从这里找到信息。
所以,我想了解的是D2D。在Android12中,Android系统自动将文件从旧设备发送到新设备(D2D)。我想阻止系统SharedPreferences默认自动发送文件(如)。所以,我必须确定dataExtractionRules 哪些文件包含或不包含。
我想要做的是排除所有文件。这意味着我可以将应用程序传输到新设备,但没有数据或缓存,就像我刚刚下载了新应用程序一样。那么,我该如何写作dataExtractionRules来实现它呢?
请检查以下代码我做了什么。
<?xml version="1.0" encoding="utf-8"?>
<data-extraction-rules>
<!-- <cloud-backup> I don't write cloud-backups in here
because i can still use android:allowBackup="false" </cloud-backup> -->
<device-transfer>
<exclude domain="root" path="where?" />
<exclude domain="file" path="where?" />
<exclude domain="database" path="where?" />
<exclude domain="sharedpref" path="com.google.android.gms.appid.xml" />
<exclude domain="sharedpref" path="user_pref.xml" />
<!-- <exclude domain="external" path="where?" /> --> …Run Code Online (Sandbox Code Playgroud) 我在底部导航视图中有 5 个图标,当我单击菜单时,我可以看到菜单的标题,如果我单击另一个图标,前一个的标题就会消失。我想继续以 XML 形式显示所有菜单的标题。我该怎么做?
这是我在活动 XML 中的代码。
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottomNV"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:backgroundTint="@color/light_gray"
app:itemIconTint="@color/black"
app:itemTextColor="@color/black"
app:menu="@menu/bottom_navigation_menu"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Run Code Online (Sandbox Code Playgroud)
这是一个菜单资源文件。
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/bottom_menu_home"
android:enabled="true"
android:icon="@drawable/bottom_home_inactive"
android:title="@string/bottom_menu_home" />
<item
android:id="@+id/bottom_menu_search"
android:enabled="true"
android:icon="@drawable/bottom_search_inactive"
android:title="@string/bottom_menu_search" />
<item
android:id="@+id/bottom_menu_message"
android:enabled="true"
android:icon="@drawable/bottom_message_inactive"
android:title="@string/bottom_menu_message" />
<item
android:id="@+id/bottom_menu_reservation"
android:enabled="true"
android:icon="@drawable/bottom_reservation_inactive"
android:title="@string/bottom_menu_reservation" />
<item
android:id="@+id/bottom_menu_myInfo"
android:enabled="true"
android:icon="@drawable/bottom_myinfo_inactive"
android:title="@string/bottom_menu_myInfo" />
Run Code Online (Sandbox Code Playgroud) android android-xml bottomnavigationview material-components-android android-bottomnavigationview
我正在尝试在 中显示用户信息DetailActivity。因此,我请求数据并从服务器获取用户的数据。但在本例中,返回类型是Flow<User>. 让我向您展示以下代码。
ServiceApi.kt
@GET("endpoint")
suspend fun getUser(@Query("id") id: Int): Response<User>
Run Code Online (Sandbox Code Playgroud)
存储库.kt
fun getUser(id: Int): Flow<User> = flow<User> {
val userResponse = api.getUser(id = id)
if (userResponse.isSuccessful) {
val user = userResponse.body()
emit(user)
}
}
.flowOn(Dispatchers.IO)
.catch { // send error }
Run Code Online (Sandbox Code Playgroud)
详细视图模型.kt
class DetailViewModel(
private val repository : Repository
) {
val uiState: StateFlow<User> = repository.getUser(id = 369).stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5000),
initialValue = User() // empty user
)
}
Run Code Online (Sandbox Code Playgroud)
详细活动.kt
class DetailActivity: …Run Code Online (Sandbox Code Playgroud) \n\n运行新的协程并阻塞当前线程,直到\n完成。不应在协程中使用此函数。它旨在将常规阻塞代码桥接到以挂起方式编写的库,以在主函数和测试中使用。
\n
我认为这意味着runBlocking仅阻止当前线程。
但Kotlin Coroutines Deep Dive所写的Marcin Moska\xc5\x82a。
\n书上说
\n\n“使用调度程序,我们可以使 runBlocking 在不同的线程上运行。但是,启动此构建器的线程仍然会被阻塞,直到协程完成为止。”
\n
我理解,即使我将当前线程更改为工作线程(或其他)线程withContext,并在工作线程中运行“runBlocking”,runBlocking仍然会阻止包括主线程在内的所有线程。
因此,我想知道的是runBlocking无论我使用什么方式总是阻塞主线程?
我现在正在学习 Android ViewModel。我有 MainActivity 和 RegisterActivity ,它们可以在其中输入姓名、年龄和电话号码。在 RegisterActivity 中输入该信息后,我将该信息放入 ViewModel 并单击一个按钮并完成 RegisterActivity。问题是,我想在 MainActivity 中显示信息。那么如何在两个活动之间共享 viewModel 呢?我必须使用什么概念?
android ×9
kotlin-flow ×2
android-12 ×1
android-bottomnavigationview ×1
android-room ×1
android-xml ×1
apk ×1
kotlin ×1
material-components-android ×1
retrofit2 ×1