gpt4 book ai didi

android - 如何使用 FLAG_GRANT_READ_URI_PERMISSION 授予对自定义内容提供程序的临时访问权限

转载 作者:塔克拉玛干 更新时间:2023-11-02 09:01:15 32 4
gpt4 key购买 nike

我正在尝试从另一个应用程序(应用程序 B)查询自定义内容提供程序(应用程序 A)。

当内容提供者没有权限保护时,我可以这样做。具体来说,我在应用程序 A 上构建了自定义内容提供程序,并将包含 URI 的 Intent 发送到应用程序 B。这是应用程序 A 中的 Intent 发送部分。

class InsertOnClickListener implements OnClickListener{        
public void onClick(View v) {
ContentValues values = new ContentValues();
values.put(DataBaseConfiguation.TableConfiguation.USER_NAME, "Jack");
Uri uri = getContentResolver().insert(DataBaseConfiguation.TableConfiguation.CONTENT_URI, values);
System.out.println("uri------------------->" + uri);
// the uri above should be like "content://com.catking.contentprovider.MyContentProvider/user"
Uri uri2 = Uri.parse("content://com.catking.contentprovider.MyContentProvider/user");
Cursor c = managedQuery(uri2, null, null, null, null);
String sendvalue = null;
if (c.moveToFirst()) {
do{
System.out.println("User name:"+c.getString(c.getColumnIndex(DataBaseConfiguation.TableConfiguation.USER_NAME)).toString());
sendvalue = c.getString(c.getColumnIndex(DataBaseConfiguation.TableConfiguation.USER_NAME)).toString();
} while (c.moveToNext());
}
Intent sendIntent = new Intent();
sendIntent.setClassName("com.android.web", "com.android.web.Provid");
sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
sendIntent.putExtra("name", uri2.toString());
sendIntent.setType("text/plain");
startActivity(sendIntent);
}
}

后面是 App A 的 list 文件。

<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:name=".ContentProviderTestActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<provider android:authorities="com.catking.contentprovider.MyContentProvider"
android:exported="true"
android:grantUriPermissions="true"
android:name="com.catking.contentprovider.MyContentProvider"
android:readPermission="android.permission.permRead"
android:writePermission="android.permission.permWrite" >
</provider>
</application>

然后App B(class Provid)获取URI并在content provider中查询相应的数据(使用以下代码)。

public class Provid extends Activity {

public void onCreate(Bundle savedInstanceState) {
Bundle extras = getIntent().getExtras();
String userNameuri;
if (extras != null) {
userNameuri = extras.getString("name");
Uri allTitles = Uri.parse(userNameuri);
Cursor c = managedQuery(allTitles, null, null, null, null);
if (c.moveToFirst()) {
do{
System.out.println("Name is"+c.getString(c.getColumnIndex(DataBaseConfiguation.TableConfiguation.USER_NAME)).toString());
} while (c.moveToNext());
}
}
}

这是应用程序 B 的 list 文件。

<uses-permission android:name="android.permission.INTERNET" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:name="._GetWebResoureActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" >
</action>
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
</activity>

<receiver android:name="StaticReceiver11" >
<intent-filter>
<action android:name="android.intent.action.MYSEND" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>

<activity
android:name="Provid"
android:label="@string/title_activity_provid" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>

</activity>
</application>

但是,当我从应用程序 B 查询内容提供者时,出现错误:

java.lang.RuntimeException: Unable to start activity ComponentInfo {com.android.web/com.android.web.Provid}: java.lang.SecurityException: Permission Denial: opening     provider com.ck.contentprovider.MyContentProvider from ProcessRecord{426c6ea8 17032:com.android.web/u0a95} (pid=17032, uid=10095) requires android.permission.permRead or android.permission.permWrite   

看来App B并没有使用临时权限访问。换句话说,如何使用应用程序 B 中的 FLAG_GRANT_READ_URI_PERMISSION?

我也试过直接将 Uri 添加到 intent(使用 setData()),而不是 Uri.toString()(使用 putExtra())。

sendIntent.setData(uri2);

Uri userNameuri = getIntent().getData(); 

但是在App B中获取到的“userNameuri”为null。

我完全糊涂了...

已更新

我根据之前的帖子尝试了“grantUriPermission("com.android.getCPaccess", uri2, Intent.FLAG_GRANT_READ_URI_PERMISSION)”
What is the correct permission handling when sending sensitive app data as email attachment?

而且确实有效。它可以在不使用 FLAG_GRANT_READ_URI_PERMISSION 的情况下工作。但许可不是“临时的”。它必须通过 revokeUriPermission() 手动结束。

所以,我想知道是否有一种方法可以像 FLAG_GRANT_READ_URI_PERMISSION 中介绍的那样授予临时权限,或者这根本就是一个错误?

最佳答案

FLAG_GRANT_READ_URI_PERMISSION 似乎只影响 Uri Intent.mData 而不是 extras 中的 uris。

我在玩 ACTION_SEND 时发现了类似的问题,它在 EXTRA_STREAM 中获取一个 uri。在 setData() 中提供相同的 uri 会起作用,但不符合规则并会导致意外行为(例如 Gmail 收件人)。

Jelly Bean intents 可以包含 ClipData,这应该可以解决问题。对于 ACTION_SEND,它是从 extras 中自动生成的。

grantUriPermission 将起作用,但需要 revokeUriPermission。要完成与 startActivity(Intent.createChooser(intent, title)) 相同的工作,您必须选择目标 (ACTION_PICK_ACTIVITY),授予对其包的权限并撤销它们当不再需要时(onActivityResult?)。

这是一些代码:

接收器应用:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.handler" >

<application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" >

<activity
android:name=".ActivityView"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="*/*"/>
</intent-filter>
</activity>
</application>
</manifest>

ActivityView.java:

protected void onCreate(Bundle savedInstanceState) {
Intent intent = getIntent();
if ((intent != null)) {
procUri(intent.getData());
procUri(intent.<Uri>getParcelableExtra(Intent.EXTRA_STREAM));
}
}

private void procUri(Uri uri) {
if (uri != null) {
InputStream i;
try {
i = getContentResolver().openInputStream(uri);
byte[] b = new byte[i.available()];
i.read(b);

} catch (Throwable e) {

}
}
}

发件人应用:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.sender" >

<application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" >

<activity
android:name=".ActivitySend"
android:label="@string/app_name" >
</activity>
<provider
android:name=".MyContentProvider"
android:authorities="com.example.sender.content"
android:enabled="true"
android:exported="false"
android:grantUriPermissions="true" >
</provider>
</application>
</manifest>

ActivitySend.java:

// OK!
private void doTestView(Uri uri, String type) {
startActivity(
new Intent(Intent.ACTION_VIEW)
.setDataAndType(uri, type)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET)
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
);
}

// error prior to JellyBean
// ok on JellyBean, even without explicit FLAG_GRANT_READ_URI_PERMISSION (due to generated ClipData)
private void doTestSend(Uri uri, String type, CharSequence title) {
startActivity(
Intent.createChooser(
new Intent(Intent.ACTION_SEND)
.setType(type)
.putExtra(Intent.EXTRA_STREAM, uri)
.putExtra(Intent.EXTRA_SUBJECT, title)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET)
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
,
title
)
);
}

// working but not ok, unexpected results!
private void doTestSend2(Uri uri, String type, CharSequence title) {
startActivity(
Intent.createChooser(
new Intent(Intent.ACTION_SEND)
.setDataAndType(uri, type)
.putExtra(Intent.EXTRA_STREAM, uri)
.putExtra(Intent.EXTRA_SUBJECT, title)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET)
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
,
title
)
);
}

关于android - 如何使用 FLAG_GRANT_READ_URI_PERMISSION 授予对自定义内容提供程序的临时访问权限,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13435654/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com