sourcecode

비트맵 개체를 액티비티 간에 전달하려면 어떻게 해야 합니까?

copyscript 2022. 7. 26. 23:33
반응형

비트맵 개체를 액티비티 간에 전달하려면 어떻게 해야 합니까?

내 액티비티에서는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");

실제로 비트맵을 구획 파일로 전달하면 "JAVA BINDER FAILURE" 오류가 발생합니다.비트맵을 바이트 배열로 전달하고 다음 활동에서 표시할 수 있도록 작성합니다.

여기서 솔루션을 공유했습니다.
번들을 사용하여 Android 활동 간에 이미지(비트맵)를 전달하려면 어떻게 해야 합니까?

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"));

주의: 늘 및 스케일링 비트맵에 대한 많은 체크가 필요합니다.

압축하여 송신하다Bitmap

가 너무 크면 승인된 답변이 크래시됩니다.1MB 제한인 것 같아요.Bitmap다른 파일 형식(예: JPG)으로 압축해야 합니다.ByteArray, 그러면 그것은 안전하게 통과할 수 있습니다.Intent.

실행

이 함수는 Kotlin Coroutines를 사용하여 별도의 스레드에 포함되어 있습니다.Bitmap압축이 체인으로 되어 있는 것은Bitmapurl에서 작성됩니다.String.그BitmapApplication Not Response(ANR) 오류를 피하기 위해 작성에는 별도의 스레드가 필요합니다.

사용되는 개념

  • Kotlin Coroutines 메모
  • Loading, Content, Error(LCE; 로드, 콘텐츠, 오류) 패턴은 다음과 같습니다.흥미가 있는 경우는, 이 토크와 비디오를 참조해 주세요.
  • LiveData는 데이터를 반환하는 데 사용됩니다. 노트에 제가 좋아하는 LiveData 리소스를 컴파일했습니다.
  • 스텝 3에서toBitmap()Kotlin 확장 기능으로 해당 라이브러리를 앱 종속성에 추가해야 합니다.

코드

1. 압축BitmapJPG로 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.

이 예에서는 fragment에서 서비스로 전달됩니다.2개의 액티비티간에 공유되는 것과 같은 개념입니다.

fragment.kt

ContextCompat.startForegroundService(
    context!!,
    Intent(context, AudioService::class.java).apply {
        action = CONTENT_SELECTED_ACTION
        putExtra(CONTENT_SELECTED_BITMAP_KEY, contentPlayer.image)
    })

3.3을 변환합니다.변환ByteArray다시 로 되돌아가다.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()
        }
    }

이미지가 너무 커서 스토리지에 저장할 수 없는 경우에는 비트맵에 대한 글로벌 스태틱 참조(수신 액티비티 내)를 사용하는 것을 고려해야 합니다.이러한 참조는 isChanging Configurations가 true를 반환하는 경우에만 onDestory에서 null로 리셋됩니다.

Intent에는 크기 제한이 있기 때문입니다.퍼블릭 스태틱오브젝트를 사용하여 서비스에서 브로드캐스트로 비트맵을 전달합니다.

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();
            }
        });
    }

My Broadcast Receiver

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);
            }
        }
    };

늦었지만 도움이 될 수 있어요.첫 번째 단편이나 액티비티에서 클래스를 선언...예를들면

   @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;
}

그리고 두 번째 클래스/프래그먼트에서는 이렇게 합니다.

Bitmap bm = postFragment.constan.photoMap;
final String itemName = postFragment.constan.namePass;

도움이 됐으면 좋겠다.

모든 위의 솔루션 저로서는, 위의 모든솔루션이 작동하지 않습니다로 비트 맵을 보내는 것은 작동하지 않는다.비트맵을 다음으로 보냅니다.parceableByteArray또한 오류에러도 생성합니다를 생성합니다.android.os.TransactionTooLargeException: data parcel size..

솔루션

  1. 비트맵을 내부 스토리지에 다음과 같이 저장:
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;
    }
  1. 그리고 송부하다 보내putExtra(String)as~하듯이
Intent intent = new Intent(ActivitySketcher.this,ActivityEditor.class);
intent.putExtra("KEY", saveBitmap(bmp));
startActivity(intent);
  1. 기타 활동에서는 다음과 같이 수령합니다.
if(getIntent() != null){
  try {
           src = BitmapFactory.decodeStream(openFileInput("myImage"));
       } catch (FileNotFoundException e) {
            e.printStackTrace();
      }

 }


비트맵 전송을 만들 수 있습니다. 시도해 보십시오.

첫 번째 클래스에서:

1) 작성:

private static Bitmap bitmap_transfer;

2) getter 및 setter 작성

public static Bitmap getBitmap_transfer() {
    return bitmap_transfer;
}

public static void setBitmap_transfer(Bitmap bitmap_transfer_param) {
    bitmap_transfer = bitmap_transfer_param;
}

3) 이미지 설정:

ImageView image = (ImageView) view.findViewById(R.id.image);
image.buildDrawingCache();
setBitmap_transfer(image.getDrawingCache());

그리고 두 번째 수업에서는:

ImageView image2 = (ImageView) view.findViewById(R.id.img2);
imagem2.setImageDrawable(new BitmapDrawable(getResources(), classe1.getBitmap_transfer()));

나의 경우, 위에서 말한 방식은 나에게 효과가 없었다.비트맵을 인텐트에 넣을 때마다 두 번째 액티비티가 시작되지 않았습니다.비트맵을 바이트[]로 전달했을 때도 마찬가지였습니다.

링크를 따라갔더니 매우 빠르게 동작했습니다.

package your.packagename

import android.graphics.Bitmap;

public class CommonResources { 
      public static Bitmap photoFinishBitmap = null;
}

내 첫 번째 경험:

Constants.photoFinishBitmap = photoFinishBitmap;
Intent intent = new Intent(mContext, ImageViewerActivity.class);
startActivity(intent);

두 번째 액티비티의 onCreate()는 다음과 같습니다.

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Bitmap photo = Constants.photoFinishBitmap;
    if (photo != null) {
        mViewHolder.imageViewerImage.setImageDrawable(new BitmapDrawable(getResources(), photo));
    }
}

언급URL : https://stackoverflow.com/questions/2459524/how-can-i-pass-a-bitmap-object-from-one-activity-to-another

반응형