我刚才的问题( 是否有可能通过数据URL分享Android上的图像? )是关系到这个问题。 我已想出如何分享我的应用程序到另一个应用程序的图像,而无需许可文件写入到外部存储设备。 不过,我仍然得到了一些问题行为:
- 当我试图从我的手机(安卓2.2.2)将影像分享的,发生在接收应用致命错误,他们不与图像上来的。 (难道这是我的应用程序的一些操作不支持在Android 2.2.2?还是那样引起我的应用程序,而不是目标应用程序错误的结果呢?)
- 当我尝试将图像分享到Evernote,一切工作正常,但笔记被保存有时几秒钟后,我在我的应用程序的屏幕的底部(从Evernote的应用程序)得到一个消息:“java.lang.SecurityException异常:许可拒绝:从ProcessRecord开口提供商com.enigmadream.picturecode.PictureContentProvider {413db6d0 1872:com.evernote / u0a10105}(PID = 1872,UID = 10105),其不从UID 10104" 输出
- 当我尝试分享照片至Facebook,还有一个供图片矩形,但它没有画面。
下面是我的ContentProvider代码。 必须有实现基于文件的ContentProvider(尤其是查询功能)的更容易和/或更合适的方式。 我想到了很多来自查询执行的问题。 有趣的是,这也将Gmail时对我的Nexus 7非常漂亮的工作。 它拿起了附件正确的显示名称和大小了。
public class PictureContentProvider extends ContentProvider implements AutoAnimate {
public static final Uri CONTENT_URI = Uri.parse("content://com.enigmadream.picturecode.snapshot/picture.png");
private static String[] mimeTypes = {"image/png"};
private Uri generatedUri;
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
throw new RuntimeException("PictureContentProvider.delete not supported");
}
@Override
public String getType(Uri uri) {
return "image/png";
}
@Override
public Uri insert(Uri uri, ContentValues values) {
throw new RuntimeException("PictureContentProvider.insert not supported");
}
@Override
public boolean onCreate() {
generatedUri = Uri.EMPTY;
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
long fileSize = 0;
MatrixCursor result = new MatrixCursor(projection);
File tempFile;
try {
tempFile = generatePictureFile(uri);
fileSize = tempFile.length();
} catch (FileNotFoundException ex) {
return result;
}
Object[] row = new Object[projection.length];
for (int i = 0; i < projection.length; i++) {
if (projection[i].compareToIgnoreCase(MediaStore.MediaColumns.DISPLAY_NAME) == 0) {
row[i] = getContext().getString(R.string.snapshot_displaystring);
} else if (projection[i].compareToIgnoreCase(MediaStore.MediaColumns.SIZE) == 0) {
row[i] = fileSize;
} else if (projection[i].compareToIgnoreCase(MediaStore.MediaColumns.DATA) == 0) {
row[i] = tempFile;
} else if (projection[i].compareToIgnoreCase(MediaStore.MediaColumns.MIME_TYPE)==0) {
row[i] = "image/png";
}
}
result.addRow(row);
return result;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
throw new RuntimeException("PictureContentProvider.update not supported");
}
@Override
public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
return mimeTypes;
}
private File generatePictureFile(Uri uri) throws FileNotFoundException {
if (generatedUri.compareTo(uri)==0)
return new File(getContext().getFilesDir(), "picture.png");;
Context context = getContext();
String query = uri.getQuery();
String[] queryParts = query.split("&");
String pictureCode = "016OA";
int resolution = 36;
int frame = 0;
int padding = 0;
for (String param : queryParts) {
if (param.length() < 2)
continue;
if (param.substring(0,2).compareToIgnoreCase("p=") == 0) {
pictureCode = param.substring(2);
} else if (param.substring(0,2).compareToIgnoreCase("r=") == 0) {
resolution = Integer.parseInt(param.substring(2));
} else if (param.substring(0, 2).compareToIgnoreCase("f=") == 0) {
frame = Integer.parseInt(param.substring(2));
} else if (param.substring(0, 2).compareToIgnoreCase("a=") == 0) {
padding = Integer.parseInt(param.substring(2));
}
}
Bitmap picture = RenderPictureCode(pictureCode, resolution, frame, padding);
File tempFile = new File(context.getFilesDir(), "picture.png");
FileOutputStream stream;
stream = new FileOutputStream(tempFile);
picture.compress(CompressFormat.PNG, 90, stream);
try {
stream.flush();
stream.close();
} catch (IOException e) {
e.printStackTrace();
throw new Error(e);
}
picture.recycle();
generatedUri = uri;
return tempFile;
}
@Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
File tempFile = generatePictureFile(uri);
return ParcelFileDescriptor.open(tempFile, ParcelFileDescriptor.MODE_READ_ONLY);
}
...
}
我也有这个在AndroidManifest.xml文件作为的同级<activity>
元素:
<provider
android:name="PictureContentProvider"
android:authorities="com.enigmadream.picturecode.snapshot"
android:grantUriPermissions="true"
android:readPermission="com.enigmadream.picturecode.snapshot"
tools:ignore="ExportedContentProvider">
<grant-uri-permission android:path="/picture.png" />
</provider>
创建意图的代码如下所示:
resolution = mPicView.getWidth();
if (mPicView.getHeight() > resolution)
resolution = mPicView.getHeight();
String paddingText = mPadding.getEditableText().toString();
int padding;
try {
padding = Integer.parseInt(paddingText);
} catch (NumberFormatException ex) {
padding = 0;
}
Uri uri = Uri.parse(PictureContentProvider.CONTENT_URI
+ "?p=" + Uri.encode(mPicView.getPictureCode()) + "&r=" + Integer.toString(resolution)
+ "&f=" + Integer.toString(mPicView.getFrame()) + "&a=" + Integer.toString(padding));
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("image/png");
share.putExtra(Intent.EXTRA_STREAM, uri);
share.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.share_subject_made));
share.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(Intent.createChooser(share, getString(R.id.menu_share)));
编辑这里是堆栈跟踪的前两行的时候我的手机上出现的错误:
04-07 13:56:24.423:E / DatabaseUtils(19431):java.lang.SecurityException异常:权限拒绝:读取com.enigmadream.picturecode.PictureContentProvider URI内容://com.enigmadream.picturecode.snapshot/picture.png? p =&01v131 R = 36&F = 0&从PID = 19025 a = 0时,UID = 10062要求com.enigmadream.picturecode.snapshot
04-07 13:56:24.423:E / DatabaseUtils(19431):在android.content.ContentProvider $ Transport.enforceReadPermission(ContentProvider.java:271)