[java] 한 활동에서 다른 활동으로 비트 맵 객체를 전달하는 방법

내 활동에서 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();
            }
        });
    }

내 방송 수신기

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압축은 Bitmapurl에서 작성된 후에 압축 되기 때문 String입니다. Bitmap창조 회피하기 위해 별도의 스레드가 필요합니다 응용 프로그램 (ANR) 응답 없음 오류를.

사용 된 개념

  • 코 틀린 코 루틴 노트 .
  • 로드, 내용, 오류 (LCE) 패턴은 아래에 사용됩니다. 관심이 있으시면 이 대화 및 비디오 에서 더 자세히 알아볼 수 있습니다 .
  • LiveData 는 데이터를 반환하는 데 사용됩니다. 이 노트 에서 내가 좋아하는 LiveData 리소스를 컴파일했습니다 .
  • 에서는 3 단계 , toBitmap()A는 코 틀린 확장 기능 이 라이브러리를 요구 앱 종속성에 첨가한다.

암호

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 에서 Service로 전달되었습니다 . 두 활동 간에 공유되는 경우 동일한 개념 입니다.

Fragment.kt

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

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


답변

늦었지만 도움이 될 수 있습니다. 첫 번째 조각이나 활동에서 클래스를 선언하십시오 … 예를 들어

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

도움이 되길 바랍니다.