#android #android-contentprovider
#Android #android-contentprovider
Вопрос:
Я хотел бы реализовать сервис, который может передавать данные между двумя приложениями. Я внедрил экспортированный ContentProvider, который отлично работает, когда я вызываю его внутренне, но выдает «Не удалось найти поставщика для …», когда я пытаюсь использовать его из внешнего приложения.
Манифест:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.poc.transferprovider">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.TransferProvider">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<provider
android:authorities="com.example.poc.transferprovider"
android:name="com.example.poc.transferprovider.Provider"
android:exported="true"
/>
</application>
</manifest>
Поставщик:
package com.example.poc.transferprovider
import android.content.ContentProvider
import android.content.ContentValues
import android.database.Cursor
import android.database.MatrixCursor
import android.net.Uri
class Provider: ContentProvider() {
override fun onCreate(): Boolean = true
override fun query(
uri: Uri,
projection: Array<out String>?,
selection: String?,
selectionArgs: Array<out String>?,
sortOrger: String?
): Cursor {
val cursor = MatrixCursor(arrayOf("column1", "column2"))
cursor.addRow(arrayOf("value1", "value2"))
return cursor
}
override fun getType(p0: Uri): String? = null
override fun insert(p0: Uri, p1: ContentValues?): Uri? = null
override fun delete(p0: Uri, p1: String?, p2: Array<out String>?): Int = 0
override fun update(p0: Uri, p1: ContentValues?, p2: String?, p3: Array<out String>?): Int = 0
}
Вот как это вызвать:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById<Button>(R.id.button).setOnClickListener {
val cursor = contentResolver.query(Uri.parse(
"content://com.example.poc.transferprovider/Provider"),
null,
null,
null,
null)
if (cursor == null) {
Log.d("xxx","cursor is null")
return@setOnClickListener
}
while (cursor.moveToNext()) {
Log.d("xxx", "result ${cursor.getColumnIndex("column1")} ${cursor.getColumnIndex("column2")}")
}
cursor.close()
Toast.makeText(this, "transfer done", Toast.LENGTH_SHORT).show()
}
}
}
Комментарии:
1.
android:name="com.example.poc.transferprovider.Provider"
Это должно быть android: name=». Поставщик» или android:name=»com.example.poc.Provider»2.
class Provider:
Не называйте это так. Слишком общий. Мне кажется, этоclass TransferProvider:
лучше подойдет вашему приложению.3. На устройстве Android 11? Посмотрите на видимость пакета.
4. Да, я забыл, что по умолчанию используется targetSdk 30 для новых проектов, спасибо, что указали на это! Не стесняйтесь публиковать это как ответ, и я приму его.