Создание/использование временного контент-провайдера
Временный контент-провайдер — это, по сути, частный контент-провайдер, но он позволяет определённому приложению получать доступ к определённым URI. Для предоставления временного доступа этим приложениям необходимо отправить целевому приложению намерение с указанным специальным флагом. Контент-провайдеры могут активно предоставлять доступ другим приложениям и пассивно предоставлять доступ приложениям, запрашивающим временный доступ.
Пример кода для реализации временного контент-провайдера:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.jssec.android.provider.temporaryprovider">
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:name=".TemporaryActiveGrantActivity"
android:label="@string/app_name"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Temporary Content Provider -->
<!-- *** POINT 1 *** Explicitly set the exported attribute to false. -->
<provider
android:name=".TemporaryProvider"
android:authorities="org.jssec.android.provider.temporaryprovider"
android:exported="false" >
<!-- *** POINT 2 *** Specify the path to grant access temporarily with the grant-uri-permissi
on. -->
<grant-uri-permission android:path="/addresses" />
</provider>
<activity
android:name=".TemporaryPassiveGrantActivity"
android:label="@string/app_name"
android:exported="true" />
</application>
</manifest>
TemporaryProvider.java
package org.jssec.android.provider.temporaryprovider;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;
public class TemporaryProvider extends ContentProvider {
public static final String AUTHORITIY = "org.jssec.android.provider.temporaryprovider";
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.org.jssec.contenttype";
public public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.org.jssec.contenttype";
// Expose the interface that the Content Provider provides.
public interface Download {
public static final String PATH = "downloads";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITIY + "/" + PATH);
}
public interface Address {
public static final String PATH = "addresses";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITIY + "/" + PATH);
}
// UriMatcher
private static final int DOWNLOADS_CODE = 1;
private static final int DOWNLOADS_ID_CODE = 2;
private static final int ADDRESSES_CODE = 3;
private static final int ADDRESSES_ID_CODE = 4;
private static UriMatcher sUriMatcher;
static {
sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
sUriMatcher.addURI(AUTHORITIY, Download.PATH, DOWNLOADS_CODE);
sUriMatcher.addURI(AUTHORITIY, Download.PATH + "/#", DOWNLOADS_ID_CODE);
sUriMatcher.addURI(AUTHORITIY, Address.PATH, ADDRESSES_CODE);
sUriMatcher.addURI(AUTHORITIY, Address.PATH + "/#", ADDRESSES_ID_CODE);
}
// Since this is a sample program,
// query method returns the following fixed result always without using database.
private static MatrixCursor sAddressCursor = new MatrixCursor(new String[] { "_id", "city" });
static {
sAddressCursor.addRow(new String[] { "1", "New York" });
sAddressCursor.addRow(new String[] { "2", "London" });
sAddressCursor.addRow(new String[] { "3", "Paris" });
}
private static MatrixCursor sDownloadCursor = new
*Здесь текст обрывается.* Матричный курсор (новый массив {"_id", "path"});
static {
sDownloadCursor.addRow(новый массив {"1", "/sdcard/downloads/sample.jpg"});
sDownloadCursor.addRow(новый массив {"2", "/sdcard/downloads/sample.txt"});
}
@Override
public boolean onCreate() {
return true;
}
@Override
public String getType(Uri uri) {
switch (sUriMatcher.match(uri)) {
case DOWNLOADS_CODE:
case ADDRESSES_CODE:
return CONTENT_TYPE;
case DOWNLOADS_ID_CODE:
case ADDRESSES_ID_CODE:
return CONTENT_ITEM_TYPE;
default:
throw new IllegalArgumentException("Неверный URI:" + uri);
}
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// *** ТОЧКА 3 *** Обрабатывайте полученные данные запроса осторожно и безопасно,
// даже если данные поступают из приложения, которому временно предоставлен доступ.
// Здесь проверяется, соответствует ли uri ожиданиям, с помощью UriMatcher#match() и switch case.
// Проверка других параметров здесь опущена из-за примера.
// Пожалуйста, обратитесь к разделу «3.2. Осторожная и безопасная обработка входных данных».
// *** ТОЧКА 4 *** Может быть возвращена информация, которая разрешена для раскрытия временным приложениям доступа.
// От приложения зависит, можно ли раскрывать результат запроса или нет.
switch (sUriMatcher.match(uri)) {
case DOWNLOADS_CODE:
case DOWNLOADS_ID_CODE:
вернуть sDownloadCursor;
case ADDRESSES_CODE:
case ADDRESSES_ID_CODE:
вернуть sAddressCursor;
default:
бросить новое исключение IllegalArgumentException («Неверный URI:» + uri);
}
}
@Override
public Uri insert(Uri uri, ContentValues values) {
// *** ТОЧКА 3 *** Обрабатывайте полученные данные запроса осторожно и безопасно,
// даже если данные поступают из приложения, которому временно предоставлен доступ.
// Здесь проверяется, соответствует ли uri ожиданиям, с помощью UriMatcher#match() и switch case.
// Проверка других параметров здесь опущена из-за примера.
// Пожалуйста, обратитесь к разделу «3.2 Осторожная и безопасная обработка входных данных».
// *** ТОЧКА 4 *** Информация, которая разрешена к раскрытию временным приложениям доступа, может быть возвращена.
// Зависит от приложения, имеет ли выданный ID чувствительное значение или нет.
switch (sUriMatcher.match(uri)) {
case DOWNLOADS_CODE:
вернуть ContentUris.withAppendedId(Download.CONTENT_URI, 3);
case ADDRESSES_CODE:
вернуть ContentUris.withAppendedId(Address.CONTENT_URI, 4);
default:
бросить новое исключение IllegalArgumentException («Неверный URI:» + uri);
}
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
// *** ТОЧКА 3 *** Обрабатывайте полученные данные запроса осторожно и безопасно,
// даже если данные поступают из приложения, которому временно предоставлен доступ.
// Здесь проверяется, соответствует ли uri ожиданиям, с помощью UriMatcher#match() и switch case.
// Проверка других параметров здесь опущена из-за примера.
// Пожалуйста, обратитесь к разделу «3.2 Осторожная и безопасная обработка входных данных».
// *** ТОЧКА 4 *** Информация, которая разрешена к раскрытию временным приложениям доступа, может быть возвращена.
// Зависит от приложения, имеет ли количество обновлённых записей чувствительное значение или нет.
switch (sUriMatcher.match(uri)) {
case DOWNLOADS_CODE:
вернуть 5; // Возвращает количество обновленных записей
case DOWNLOADS_ID_CODE:
вернуть 1;
case ADDRESSES_CODE:
вернуть 15;
case ADDRESSES_ID_CODE:
вернуть 1; **Вот перевод текста на русский язык:**
public void onCloseClick(View view) { finish(); } }
**Ниже приведён пример временного поставщика контента.**
*Важные моменты (использование поставщика контента):*
9. Не отправляйте конфиденциальную информацию.
10. Когда вы получаете результат, будьте осторожны и безопасно обрабатывайте данные результата.
TemporaryUserActivity.java
```java
package org.jssec.android.provider.temporaryuser;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.content.pm.ProviderInfo;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class TemporaryUserActivity extends Activity {
// Информация о действии поставщика временного контента.
private static final String TARGET_PACKAGE = "org.jssec.android.provider.temporaryprovider";
private static final String TARGET_ACTIVITY = "org.jssec.android.provider.temporaryprovider.TemporaryPassiveGrantActivity";
// Целевая информация поставщика контента
private static final String AUTHORITY = "org.jssec.android.provider.temporaryprovider";
private interface Address {
public static final String PATH = "addresses";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + PATH);
}
private static final int REQUEST_CODE = 1;
public void onQueryClick(View view) {
logLine("[Query]");
Cursor cursor = null;
try {
if (!providerExists(Address.CONTENT_URI)) {
logLine(" Поставщик контента не существует.");
return;
}
// *** ТОЧКА 9 *** Не отправляйте конфиденциальную информацию.
// Если нет проблем с тем, что информация будет получена вредоносным ПО, её можно включить в запрос.
cursor = getContentResolver().query(Address.CONTENT_URI, null, null, null, null);
// *** ТОЧКА 10 *** Когда вы получаете результат, осторожно и безопасно обработайте данные результата.
// Опущено, поскольку это образец. Пожалуйста, обратитесь к разделу «3.2 Тщательная и безопасная обработка входных данных».
if (cursor == null) {
logLine(" нулевой курсор");
} else {
boolean moved = cursor.moveToFirst();
while (moved) {
logLine(String.format(" %d, %s", cursor.getInt(0), cursor.getString(1)));
moved = cursor.moveToNext();
}
}
} catch (SecurityException ex) {
logLine(" Исключение:" + ex.getMessage());
}
finally {
если (курсор != null) cursor.close();
}
}
// В случае, если это приложение запрашивает временный доступ к поставщику контента,
// и поставщик контента пассивно предоставляет этому приложению разрешение на временный доступ.
public void onGrantRequestClick(View view) {
Intent intent = new Intent();
intent.setClassName(TARGET_PACKAGE, TARGET_ACTIVITY);
try {
startActivityForResult(intent, REQUEST_CODE);
} catch (ActivityNotFoundException e) {
logLine("Активность поставщика контента не найдена.");
}
}
private boolean providerExists(Uri uri) {
ProviderInfo pi = getPackageManager().resolveContentProvider(uri.getAuthority(), 0);
return (pi != null);
}
private TextView mLogView;
// Если поставщик контента активно предоставляет этому приложению временный доступ,
// то это приложение активно запрашивает его.
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mLogView = (TextView)findViewById(R.id.logview);
}
private void logLine(String line) {
mLogView.append(line);
mLogView.append("¥n");
}
}
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )