Câu trả lời:
Bitmap
thực hiện Parcelable
, vì vậy bạn luôn có thể vượt qua nó với mục đích:
Intent intent = new Intent(this, NewActivity.class);
intent.putExtra("BitmapImage", bitmap);
và lấy nó ở đầu bên kia:
Intent intent = getIntent();
Bitmap bitmap = (Bitmap) intent.getParcelableExtra("BitmapImage");
Trên thực tế, việc truyền một bitmap dưới dạng Parcelable sẽ dẫn đến lỗi "JAVA BINDER FAILURE". Hãy thử truyền bitmap dưới dạng một mảng byte và xây dựng nó để hiển thị trong hoạt động tiếp theo.
Tôi đã chia sẻ giải pháp của mình ở đây:
làm thế nào để bạn chuyển hình ảnh (bitmap) giữa các hoạt động của Android bằng cách sử dụng các gói?
Truyền bitmap dưới dạng parcable trong gói giữa các hoạt động không phải là một ý tưởng tốt vì giới hạn kích thước của Có thể di chuyển (1mb). Bạn có thể lưu trữ bitmap trong một tệp trong bộ nhớ trong và truy xuất bitmap đã lưu trong một số hoạt động. Đây là một số mã mẫu.
Để lưu trữ bitmap trong tệp myImage trong bộ nhớ trong:
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;
}
Sau đó, trong hoạt động tiếp theo, bạn có thể giải mã tệp này myImage thành bitmap bằng mã sau:
//here context can be anything like getActivity() for fragment, this or MainActivity.this
Bitmap bitmap = BitmapFactory.decodeStream(context.openFileInput("myImage"));
Lưu ý Rất nhiều kiểm tra null và tỉ lệ bitmap là không phổ biến.
openFileOutput
.
Nếu hình ảnh quá lớn và bạn không thể lưu và tải nó vào bộ lưu trữ, bạn nên xem xét chỉ sử dụng tham chiếu tĩnh toàn cục cho bitmap (bên trong hoạt động nhận), sẽ được đặt lại thành null trên onDestory, chỉ khi "isChangingConfigurations" trả về đúng
Bởi vì Intent có giới hạn kích thước. Tôi sử dụng đối tượng tĩnh công khai để truyền bitmap từ dịch vụ sang phát sóng ....
public class ImageBox {
public static Queue<Bitmap> mQ = new LinkedBlockingQueue<Bitmap>();
}
vượt qua trong dịch vụ của tôi
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 của tôi
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
Câu trả lời được chấp nhận sẽ sụp đổ khi Bitmap
quá lớn. Tôi tin rằng đó là giới hạn 1MB . Các Bitmap
phải được nén vào một định dạng file khác nhau như một JPG đại diện bởi một ByteArray
, sau đó nó có thể được thông qua một cách an toàn thông qua một Intent
.
Hàm này được chứa trong một luồng riêng biệt bằng cách sử dụng Kotlin Coroutines vì việc Bitmap
nén được xâu chuỗi sau khi Bitmap
được tạo từ một url String
. Việc Bitmap
tạo yêu cầu một luồng riêng biệt để tránh các lỗi Ứng dụng không phản hồi (ANR) .
toBitmap()
là một chức năng mở rộng Kotlin yêu cầu thư viện đó được thêm vào các phụ thuộc ứng dụng.Bitmap
vào JPG ByteArray
sau khi được tạo.Kho lưu trữ.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}")
}
}
})
}
ByteArray
thông qua một Intent
.Trong mẫu này, nó được chuyển từ Fragment sang Service . Đó là khái niệm tương tự nếu được chia sẻ giữa hai Hoạt động .
Mảnh vỡ
ContextCompat.startForegroundService(
context!!,
Intent(context, AudioService::class.java).apply {
action = CONTENT_SELECTED_ACTION
putExtra(CONTENT_SELECTED_BITMAP_KEY, contentPlayer.image)
})
ByteArray
trở lại Bitmap
.Sử dụng.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()
}
}
Nó có thể muộn nhưng có thể giúp. Trên đoạn hoặc hoạt động đầu tiên, hãy khai báo một lớp ... ví dụ
@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;
}
Sau đó, trên lớp thứ hai / đoạn làm điều này ..
Bitmap bm = postFragment.constan.photoMap;
final String itemName = postFragment.constan.namePass;
Hy vọng nó giúp.
Tất cả các giải pháp trên không hoạt động với tôi, Gửi bitmap parceableByteArray
cũng tạo ra lỗi android.os.TransactionTooLargeException: data parcel size
.
Giải pháp
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;
}
putExtra(String)
dưới dạngIntent intent = new Intent(ActivitySketcher.this,ActivityEditor.class);
intent.putExtra("KEY", saveBitmap(bmp));
startActivity(intent);
if(getIntent() != null){
try {
src = BitmapFactory.decodeStream(openFileInput("myImage"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
Bạn có thể tạo chuyển bitmap. thử cái này....
Trong lớp đầu tiên:
1) Tạo:
private static Bitmap bitmap_transfer;
2) Tạo getter và setter
public static Bitmap getBitmap_transfer() {
return bitmap_transfer;
}
public static void setBitmap_transfer(Bitmap bitmap_transfer_param) {
bitmap_transfer = bitmap_transfer_param;
}
3) Đặt hình ảnh:
ImageView image = (ImageView) view.findViewById(R.id.image);
image.buildDrawingCache();
setBitmap_transfer(image.getDrawingCache());
Sau đó, trong lớp thứ hai:
ImageView image2 = (ImageView) view.findViewById(R.id.img2);
imagem2.setImageDrawable(new BitmapDrawable(getResources(), classe1.getBitmap_transfer()));
Trong trường hợp của tôi, cách được đề cập ở trên không làm việc cho tôi. Mỗi lần tôi đưa bitmap vào mục đích, hoạt động thứ 2 không bắt đầu. Điều tương tự cũng xảy ra khi tôi truyền bitmap dưới dạng byte [].
Tôi đã theo liên kết này và nó hoạt động như một bùa mê và rất nhanh:
package your.packagename
import android.graphics.Bitmap;
public class CommonResources {
public static Bitmap photoFinishBitmap = null;
}
trong acitiviy đầu tiên của tôi:
Constants.photoFinishBitmap = photoFinishBitmap;
Intent intent = new Intent(mContext, ImageViewerActivity.class);
startActivity(intent);
và đây là onCreate () của Hoạt động thứ 2 của tôi:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bitmap photo = Constants.photoFinishBitmap;
if (photo != null) {
mViewHolder.imageViewerImage.setImageDrawable(new BitmapDrawable(getResources(), photo));
}
}
CommonResources.photoFinishBitmap
thay vì Constants.photoFinishBitmap
.
URI
hoặcResourceID
của bitmap chứ không phải chính bitmap. Vượt qua toàn bộ bitmap đòi hỏi rất nhiều bộ nhớ. Việc truyền URL đòi hỏi rất ít bộ nhớ và cho phép mỗi hoạt động tải và chia tỷ lệ bitmap khi chúng cần.