비트 맵에 대한 Android 공유 의도-공유 전에 저장하지 않을 수 있습니까?
임시 위치에 대한 파일을 저장하지 않고 공유 의도를 사용하여 내 앱에서 비트 맵을 내보내려고합니다. 내가 찾은 모든 예제는 2 단계입니다. 1) SD 카드에 저장하고 해당 파일에 대한 Uri를 만듭니다. 2)이 Uri로 인 텐트를 시작합니다.
WRITE_EXTERNAL_STORAGE 권한을 요구하지 않고 파일을 저장하고 나중에 제거하는 것이 가능합니까? ExternalStorage없이 장치 주소를 지정하는 방법은 무엇입니까?
나는 이와 같은 문제가 있었다. 외부 저장소 읽기 및 쓰기 권한을 요청하고 싶지 않았습니다. 또한 때로는 휴대폰에 SD 카드가 없거나 카드가 마운트 해제 될 때 문제가 발생합니다.
다음 메서드는 FileProvider 라는 ContentProvider를 사용합니다 . 기술적으로 공유하기 전에 비트 맵 (내부 저장소에)을 저장하지만 권한을 요청할 필요가 없습니다. 또한 비트 맵을 공유 할 때마다 이미지 파일을 덮어 씁니다. 내부 캐시에 있기 때문에 사용자가 앱을 제거하면 삭제됩니다. 그래서 제 생각에는 이미지를 저장하지 않는 것만 큼 좋습니다. 이 방법은 외부 저장소에 저장하는 것보다 더 안전합니다.
문서는 꽤 훌륭하지만 (아래의 추가 자료 참조) 일부 부분은 약간 까다 롭습니다. 다음은 나를 위해 일한 요약입니다.
매니페스트에서 FileProvider 설정
<manifest>
...
<application>
...
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.example.myapp.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
...
</application>
</manifest>
com.example.myapp
앱 패키지 이름으로 바꿉니다 .
res / xml / filepaths.xml 생성
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<cache-path name="shared_images" path="images/"/>
</paths>
이것은 FileProvider에게 공유 할 파일을 가져올 위치를 알려줍니다 (이 경우 캐시 디렉토리 사용).
내부 저장소에 이미지 저장
// save bitmap to cache directory
try {
File cachePath = new File(context.getCacheDir(), "images");
cachePath.mkdirs(); // don't forget to make the directory
FileOutputStream stream = new FileOutputStream(cachePath + "/image.png"); // overwrites this image every time
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
이미지 공유
File imagePath = new File(context.getCacheDir(), "images");
File newFile = new File(imagePath, "image.png");
Uri contentUri = FileProvider.getUriForFile(context, "com.example.myapp.fileprovider", newFile);
if (contentUri != null) {
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // temp permission for receiving app to read this file
shareIntent.setDataAndType(contentUri, getContentResolver().getType(contentUri));
shareIntent.putExtra(Intent.EXTRA_STREAM, contentUri);
startActivity(Intent.createChooser(shareIntent, "Choose an app"));
}
추가 읽기
임시 위치에 대한 파일을 저장하지 않고 공유 의도를 사용하여 내 앱에서 비트 맵을 내보내려고합니다.
이론적으로 이것은 가능합니다. 실제로는 불가능할 것입니다.
이론적으로 공유해야하는 Uri
것은 비트 맵으로 해석되는 것입니다. 가장 간단한 방법은 외부 저장소와 같이 다른 응용 프로그램에서 직접 액세스 할 수있는 파일 인 경우입니다.
플래시에 전혀 쓰지 않으려면 자체 ContentProvider
를 구현 openFile()
하고 메모리 내 비트 맵을 반환 하도록 구현하는 방법을 파악한 다음 Uri
해당 비트 맵을 ACTION_SEND
Intent
. openFile()
를 반환해야하기 때문에 ParcelFileDescriptor
디스크에 표시하지 않으면 어떻게 할 수 있을지 모르겠지만 검색하는 데 많은 시간을 소비하지 않았습니다.
WRITE_EXTERNAL_STORAGE 권한을 요구하지 않고 파일을 저장하고 나중에 제거하는 것이 가능합니까?
단순히 외부 저장소에 저장하지 않으려면 ContentProvider
내부 저장소의 파일을 사용하여 경로를 이동할 수 있습니다 . 이 샘플 프로젝트 는 장치의 PDF 뷰어를 ContentProvider
통해 PDF 파일을 제공하는를 보여줍니다 ACTION_VIEW
. 동일한 접근 방식을 ACTION_SEND
.
CardView를 이미지로 공유 한 다음 앱 내부 저장 영역의 캐시 하위 디렉터리에 저장하기위한 것입니다. 도움이 되길 바랍니다.
@Override
public void onClick(View view) {
CardView.setDrawingCacheEnabled(true);
CardView.buildDrawingCache();
Bitmap bitmap = CardView.getDrawingCache();
try{
File file = new File(getContext().getCacheDir()+"/Image.png");
bitmap.compress(Bitmap.CompressFormat.PNG,100,new FileOutputStream(file));
Uri uri = FileProvider.getUriForFile(getContext(),"com.mydomain.app", file);
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
shareIntent.setType("image/jpeg");
getContext().startActivity(Intent.createChooser(shareIntent, "Share"));
}catch (FileNotFoundException e) {e.printStackTrace();}
}
});
저장 권한 없이도 쉽고 짧은 솔루션 을 찾는 분이라면 누구든지 (누가 7.0도 지원합니다). 여기있어.
매니페스트에 추가
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
이제 provider_paths.xml 생성
<paths>
<external-path name="external_files" path="."/>
</paths>
마지막으로이 메서드를 활동 / 조각에 추가합니다 (rootView는 공유하려는보기입니다).
private void ShareIt(View rootView){
if (rootView != null && context != null && !context.isFinishing()) {
rootView.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(rootView.getDrawingCache());
if (bitmap != null ) {
//Save the image inside the APPLICTION folder
File mediaStorageDir = new File(AppContext.getInstance().getExternalCacheDir() + "Image.png");
try {
FileOutputStream outputStream = new FileOutputStream(String.valueOf(mediaStorageDir));
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
outputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if (ObjectUtils.isNotNull(mediaStorageDir)) {
Uri imageUri = FileProvider.getUriForFile(getActivity(), getActivity().getApplicationContext().getPackageName() + ".provider", mediaStorageDir);
if (ObjectUtils.isNotNull(imageUri)) {
Intent waIntent = new Intent(Intent.ACTION_SEND);
waIntent.setType("image/*");
waIntent.putExtra(Intent.EXTRA_STREAM, imageUri);
startActivity(Intent.createChooser(waIntent, "Share with"));
}
}
}
}
}
여기에 방법을 작동하는 것은 할 자신의 응용 프로그램의 스크린 샷을 확인 하고 공유하는 모든 메신저 또는 이메일 클라이언트를 통해 이미지로.
수정하려면 업데이트되지 비트 맵을 내가 개선 문제를 Suragch '사용의 대답을 Gurupad Mamadapur 의 의견과 추가 자신의 수정'.
Here is code in Kotlin language:
private lateinit var myRootView:View // root view of activity
@SuppressLint("SimpleDateFormat")
private fun shareScreenshot() {
// We need date and time to be added to image name to make it unique every time, otherwise bitmap will not update
val sdf = SimpleDateFormat("yyyyMMdd_HHmmss")
val currentDateandTime = sdf.format(Date())
val imageName = "/image_$currentDateandTime.jpg"
// CREATE
myRootView = window.decorView.rootView
myRootView.isDrawingCacheEnabled = true
myRootView.buildDrawingCache(true) // maybe You dont need this
val bitmap = Bitmap.createBitmap(myRootView.drawingCache)
myRootView.isDrawingCacheEnabled = false
// SAVE
try {
File(this.cacheDir, "images").deleteRecursively() // delete old images
val cachePath = File(this.cacheDir, "images")
cachePath.mkdirs() // don't forget to make the directory
val stream = FileOutputStream("$cachePath$imageName")
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, stream) // can be png and any quality level
stream.close()
} catch (ex: Exception) {
Toast.makeText(this, ex.javaClass.canonicalName, Toast.LENGTH_LONG).show() // You can replace this with Log.e(...)
}
// SHARE
val imagePath = File(this.cacheDir, "images")
val newFile = File(imagePath, imageName)
val contentUri = FileProvider.getUriForFile(this, "com.example.myapp.fileprovider", newFile)
if (contentUri != null) {
val shareIntent = Intent()
shareIntent.action = Intent.ACTION_SEND
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // temp permission for receiving app to read this file
shareIntent.type = "image/jpeg" // just assign type. we don't need to set data, otherwise intent will not work properly
shareIntent.putExtra(Intent.EXTRA_STREAM, contentUri)
startActivity(Intent.createChooser(shareIntent, "Choose app"))
}
}
'programing tip' 카테고리의 다른 글
jquery 부드러운 스크롤을 앵커로? (0) | 2020.11.29 |
---|---|
10 미만은 숫자에 0을 더합니다. (0) | 2020.11.29 |
Flask 및 uWSGI-앱 0을로드 할 수 없음 (mountpoint = '') (호출 가능을 찾을 수 없음 또는 가져 오기 오류) (0) | 2020.11.29 |
DateTime을 TimeSpan으로 변환 (0) | 2020.11.29 |
UIButton 하위 클래스를 초기화하는 방법은 무엇입니까? (0) | 2020.11.29 |