한 활동에서 다른 활동으로 비트 맵 객체를 전달하는 방법
내 활동에서 Bitmap
객체를 만든 다음 다른 객체를 시작해야 합니다. 하위 액티비티 ( Activity
이 Bitmap
객체 를 시작할 액티비티)에서 어떻게이 객체를 전달할 수 있습니까?
Bitmap
구현 Parcelable
하여 항상 의도와 함께 전달할 수 있습니다.
Intent intent = new Intent(this, NewActivity.class);
intent.putExtra("BitmapImage", bitmap);
다른 쪽 끝에서 검색하십시오.
Intent intent = getIntent();
Bitmap bitmap = (Bitmap) intent.getParcelableExtra("BitmapImage");
실제로 비트 맵을 Parcelable로 전달하면 "JAVA BINDER FAILURE"오류가 발생합니다. 비트 맵을 바이트 배열로 전달하고 다음 액티비티에서 표시 할 수 있도록 빌드하십시오.
내 솔루션을 여기에서 공유했습니다 :
번들을 사용하여 안드로이드 활동간에 이미지 (비트 맵)를 어떻게 전달합니까?
Parceable (1mb)의 크기 제한으로 인해 활동간에 번들에서 구문 분석 가능한 비트 맵을 전달하는 것은 좋지 않습니다. 비트 맵을 내부 저장소의 파일에 저장하고 여러 작업에서 저장된 비트 맵을 검색 할 수 있습니다. 샘플 코드는 다음과 같습니다.
내부 저장소 의 파일 myImage 에 비트 맵을 저장하려면
public String createImageFromBitmap(Bitmap bitmap) {
String fileName = "myImage";//no .png or .jpg needed
try {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
FileOutputStream fo = openFileOutput(fileName, Context.MODE_PRIVATE);
fo.write(bytes.toByteArray());
// remember close file output
fo.close();
} catch (Exception e) {
e.printStackTrace();
fileName = null;
}
return fileName;
}
다음 활동에서는 다음 코드를 사용하여이 파일 myImage를 비트 맵으로 디코딩 할 수 있습니다.
//here context can be anything like getActivity() for fragment, this or MainActivity.this
Bitmap bitmap = BitmapFactory.decodeStream(context.openFileInput("myImage"));
참고 null 및 스케일링 비트 맵을 많이 검사하지 않아도됩니다.
이미지가 너무 커서 저장소에 저장 및로드 할 수없는 경우 비트 맵에 대한 전역 정적 참조 (수신 활동 내부)를 사용하는 것을 고려해야합니다. "isChangingConfigurations"인 경우에만 onDestory에서 null로 재설정됩니다. true를 반환합니다.
의도에는 크기 제한이 있기 때문입니다. 공용 정적 객체를 사용하여 서비스에서 브로드 캐스트로 비트 맵을 전달합니다 ....
public class ImageBox {
public static Queue<Bitmap> mQ = new LinkedBlockingQueue<Bitmap>();
}
내 서비스에 전달
private void downloadFile(final String url){
mExecutorService.submit(new Runnable() {
@Override
public void run() {
Bitmap b = BitmapFromURL.getBitmapFromURL(url);
synchronized (this){
TaskCount--;
}
Intent i = new Intent(ACTION_ON_GET_IMAGE);
ImageBox.mQ.offer(b);
sendBroadcast(i);
if(TaskCount<=0)stopSelf();
}
});
}
내 BroadcastReceiver
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
LOG.d(TAG, "BroadcastReceiver get broadcast");
String action = intent.getAction();
if (DownLoadImageService.ACTION_ON_GET_IMAGE.equals(action)) {
Bitmap b = ImageBox.mQ.poll();
if(b==null)return;
if(mListener!=null)mListener.OnGetImage(b);
}
}
};
압축 및 보내기 Bitmap
Bitmap
이 너무 크면 허용되는 답변이 중단됩니다 . 나는 그것이 1MB 제한 이라고 생각합니다 . 가 Bitmap
같은 같은 다른 파일 포맷으로 압축되어야 JPG a로 나타내어 ByteArray
, 그것은 안전하게 통해 전달 될 수있다 Intent
.
이행
이 함수는 Kotlin Coroutines를 사용하여 별도의 스레드에 포함되어 있습니다. Bitmap
압축은 Bitmap
URL에서 작성된 후에 압축 되기 때문 String
입니다. Bitmap
창조 회피하기 위해 별도의 스레드가 필요합니다 응용 프로그램 (ANR) 응답 없음 오류를.
사용 된 개념
- 코 틀린 코 루틴 노트 .
- 로드, 내용, 오류 (LCE) 패턴은 아래에 사용됩니다. 관심이 있으시면 이 대화 및 비디오 에서 더 자세히 알아볼 수 있습니다 .
- LiveData 는 데이터를 반환하는 데 사용됩니다. 이 노트 에서 내가 좋아하는 LiveData 리소스를 컴파일했습니다 .
- 에서는 3 단계 ,
toBitmap()
A는 코 틀린 확장 기능 이 라이브러리를 요구 앱 종속성에 첨가한다.
암호
1. 압축 Bitmap
을 JPG는 ByteArray
그것이 생성 된 후에.
Repository.kt
suspend fun bitmapToByteArray(url: String) = withContext(Dispatchers.IO) {
MutableLiveData<Lce<ContentResult.ContentBitmap>>().apply {
postValue(Lce.Loading())
postValue(Lce.Content(ContentResult.ContentBitmap(
ByteArrayOutputStream().apply {
try {
BitmapFactory.decodeStream(URL(url).openConnection().apply {
doInput = true
connect()
}.getInputStream())
} catch (e: IOException) {
postValue(Lce.Error(ContentResult.ContentBitmap(ByteArray(0), "bitmapToByteArray error or null - ${e.localizedMessage}")))
null
}?.compress(CompressFormat.JPEG, BITMAP_COMPRESSION_QUALITY, this)
}.toByteArray(), "")))
}
}
ViewModel.kt
//Calls bitmapToByteArray from the Repository
private fun bitmapToByteArray(url: String) = liveData {
emitSource(switchMap(repository.bitmapToByteArray(url)) { lce ->
when (lce) {
is Lce.Loading -> liveData {}
is Lce.Content -> liveData {
emit(Event(ContentResult.ContentBitmap(lce.packet.image, lce.packet.errorMessage)))
}
is Lce.Error -> liveData {
Crashlytics.log(Log.WARN, LOG_TAG,
"bitmapToByteArray error or null - ${lce.packet.errorMessage}")
}
}
})
}
2.를 ByteArray
통해 이미지를 전달하십시오 Intent
.
In this sample it's passed from a Fragment to a Service. It's the same concept if being shared between two Activities.
Fragment.kt
ContextCompat.startForegroundService(
context!!,
Intent(context, AudioService::class.java).apply {
action = CONTENT_SELECTED_ACTION
putExtra(CONTENT_SELECTED_BITMAP_KEY, contentPlayer.image)
})
3. Convert ByteArray
back to Bitmap
.
Utils.kt
fun ByteArray.byteArrayToBitmap(context: Context) =
run {
BitmapFactory.decodeByteArray(this, BITMAP_OFFSET, size).run {
if (this != null) this
// In case the Bitmap loaded was empty or there is an error I have a default Bitmap to return.
else AppCompatResources.getDrawable(context, ic_coinverse_48dp)?.toBitmap()
}
}
It might be late but can help. On the first fragment or activity do declare a class...for example
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
description des = new description();
if (requestCode == PICK_IMAGE_REQUEST && data != null && data.getData() != null) {
filePath = data.getData();
try {
bitmap = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), filePath);
imageView.setImageBitmap(bitmap);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
constan.photoMap = bitmap;
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static class constan {
public static Bitmap photoMap = null;
public static String namePass = null;
}
Then on the second class/fragment do this..
Bitmap bm = postFragment.constan.photoMap;
final String itemName = postFragment.constan.namePass;
Hope it helps.
You can create a bitmap transfer. try this....
In the first class:
1) Create:
private static Bitmap bitmap_transfer;
2) Create getter and setter
public static Bitmap getBitmap_transfer() {
return bitmap_transfer;
}
public static void setBitmap_transfer(Bitmap bitmap_transfer_param) {
bitmap_transfer = bitmap_transfer_param;
}
3) Set the image:
ImageView image = (ImageView) view.findViewById(R.id.image);
image.buildDrawingCache();
setBitmap_transfer(image.getDrawingCache());
Then, in the second class:
ImageView image2 = (ImageView) view.findViewById(R.id.img2);
imagem2.setImageDrawable(new BitmapDrawable(getResources(), classe1.getBitmap_transfer()));
All of the above solutions doesn't work for me, Sending bitmap as parceableByteArray
also generates error android.os.TransactionTooLargeException: data parcel size
.
Solution
- Saved the bitmap in internal storage as:
public String saveBitmap(Bitmap bitmap) {
String fileName = "ImageName";//no .png or .jpg needed
try {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
FileOutputStream fo = openFileOutput(fileName, Context.MODE_PRIVATE);
fo.write(bytes.toByteArray());
// remember close file output
fo.close();
} catch (Exception e) {
e.printStackTrace();
fileName = null;
}
return fileName;
}
- and send in
putExtra(String)
as
Intent intent = new Intent(ActivitySketcher.this,ActivityEditor.class);
intent.putExtra("KEY", saveBitmap(bmp));
startActivity(intent);
- and Receive it in other activity as:
if(getIntent() != null){
try {
src = BitmapFactory.decodeStream(openFileInput("myImage"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
In my case, the way mentioned above didn't worked for me. Every time I put the bitmap in the intent, the 2nd activity didn't start. The same happened when I passed the bitmap as byte[].
I followed this link and it worked like a charme and very fast:
package your.packagename
import android.graphics.Bitmap;
public class CommonResources {
public static Bitmap photoFinishBitmap = null;
}
in my 1st acitiviy:
Constants.photoFinishBitmap = photoFinishBitmap;
Intent intent = new Intent(mContext, ImageViewerActivity.class);
startActivity(intent);
and here is the onCreate() of my 2nd Activity:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bitmap photo = Constants.photoFinishBitmap;
if (photo != null) {
mViewHolder.imageViewerImage.setImageDrawable(new BitmapDrawable(getResources(), photo));
}
}
'IT story' 카테고리의 다른 글
오류 : Jack은 Java 8 언어 기능을 지원해야합니다. (0) | 2020.06.24 |
---|---|
iPhone / iPad Simulator의 크기를 조정하는 방법은 무엇입니까? (0) | 2020.06.24 |
루비에서 블록에 대한 do..end vs 중괄호 (0) | 2020.06.24 |
jQuery를 사용하여 href 값을 얻는 방법? (0) | 2020.06.24 |
"git diff"를 수행 할 때 어떻게 나란히 diff를 얻을 수 있습니까? (0) | 2020.06.24 |