Я застрял на этой проблеме в течение нескольких дней. Если какой-нибудь небольшой комментарий поможет спасти одного программиста... У меня есть два действия A и B. Действие — это действие, которое вызывает действие B в startActivityForResult(). Действие B — это действие камеры, к которому добавлена камера. И изображения, которые делает действие B, должны быть отправлены обратно в действие A.
Фотографии, которые я делаю, получены байт [] данные через PictureCallback. И вот проблема. Я ожидаю, что пользователь сделает как минимум 2-3 (или более) изображения, поэтому я попытался сделать эти массивы байтов формой списка.
Список растровых изображений невозможен, потому что он вызывает ошибку НЕУДАЧНАЯ ТРАНЗАКЦИЯ BINDER, когда его размер превышает 40 КБ.
ArrayList<байт[]> не является Parcelable, поэтому его невозможно добавить в данные Intent Extra.
Я попытался сохранить каждый байт [] данных фотографий в намерение Extra с помощью цикла for. Но из-за (я думаю) проблемы с емкостью приложение обновляется после завершения действия B. (Это не ловится на logcat, потому что это не приводит к сбою приложения)
Я не включал никаких кодов, потому что думаю, что это не нужно. Если вам интересно, я сразу же покажу вам любые коды, которые вам нравятся.
Если бы какие-то лучшие способы или небольшие отзывы о моих испытаниях много значили бы для меня. И будьте ОЧЕНЬ благодарны. Спасибо за прочтение!
Деятельность
public class A_Activity extends AppCompatActivity{
private static final int CAMERA_REQUEST_CODE = 101;
private FrameLayout accidentFrame;
private FragmentManager manager;
......
ArrayList< byte[] > sending_list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_accident_record);
sending_list = new ArrayList<>();
....
// button that moves to B Activity
findViewById(R.id.btnCamera).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent cameraIntent = new Intent(A_Activity.this, B_Activity.class);
........
startActivityForResult(cameraIntent, CAMERA_REQUEST_CODE);
}
});
//
....
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
if (requestCode == CAMERA_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
int size = data.getExtras().getInt("array_size");
for(int i = 0; i<size ; i++){
sending_list.add(data.getByteArrayExtra("byte_array" + i));
}
}
}
}
private void sendResult() {
// There is a reason using map!
HashMap<String, ArrayList<byte[]>> thisMap = new HashMap<>();
thisMap.put("0", sending_list);
Intent picturesData = new Intent();
picturesData.putExtra("data_map", thisMap);
startActivity(new Intent(A_Activity.this, C_Activity.class));
}
}
B_Activity (активность камеры)
public class B_Activity extends AppCompatActivity{
....
Camera camera;
FrameLayout appCamera;
CameraSurfaceAdapter cameraAdapter;
Button btnCapture;
TextView btnFinish;
ArrayList<byte[]> byteArray;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_accident_camera);
.....
appCamera = findViewById(R.id.appCamera);
if (camera == null) {
camera = Camera.open();
}
cameraAdapter = new CameraSurfaceAdapter(getApplicationContext(), camera);
appCamera.addView(cameraAdapter);
// take picture
byteArray = new ArrayList<byte[]>();
btnCapture = findViewById(R.id.btnCapture);
btnCapture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
takePicture();
}
});
btnFinish = findViewById(R.id.btnFinish);
btnFinish.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (byteArray != null){
Intent dataIntent = new Intent();
dataIntent.putExtra("array_size", byteArray.size());
for(int i = 0; i<byteArray.size() ; i++){
dataIntent.putExtra("byte_array" + i, byteArray.get(i));
}
setResult(RESULT_OK, dataIntent);
finish();
}
});
}
private void takePicture() {
if (camera != null) {
camera.takePicture(null, null, mPictureCallback);
} else {
}
}
Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
byteArray.add(data);
camera.startPreview();
savePhoto(data);
}
};
.......
@Override
public void onBackPressed() {
btnFinish.performClick();
}
@Override
public void onDestroy() {
super.onDestroy();
camera.stopPreview();
camera.release();
camera = null;
}
}
сделать оба фрагмента деятельности вы имеете в виду?
B деятельность сделать фрагмент.
Еще один простой, но довольно грязный подход, который я бы рассмотрел при обмене большими данными между действиями, — это просто хранить их в синглтоне.
@AkioAlex загрузил код! Спасибо
Не проходите мимо изображения. Это неэффективно, и вы довольно быстро достигнете пределов размера. Просто передайте ссылку, как вы получили в onActivityResult()
от камеры. Или, если необходимо, сохраните этот файл изображения где-нибудь (SD-карта, личное хранилище) и передайте ему Uri. Не передавать двоичный BLOB-объект.
Спасибо. Я просто подойду к проблеме иначе. Спасибо!
но что вы имеете в виду, передавая ссылку?
Это означает, что просто временно сохраните изображение в локальном хранилище. затем отправьте его URL-адрес/путь к следующему действию. открыть изображение с этого URL. Поскольку передача изображения в массив байтов также замедляется при открытии новой активности.
сделал это ! Еще раз спасибо :) Думаю, я поступил так глупо
Передать массив байтов в намерение: -
Intent intent = new Intent(this, NextActivity.class);
intent.putExtra("picture", byteArray);
startActivity(intent);
Получить массив байтов из пакета и преобразовать в растровое изображение: -
Bundle extras = getIntent().getExtras();
byte[] byteArray = extras.getByteArray("picture");
Моя мысль состоит в том, чтобы использовать Фрагмент. Фрагмент поможет вам в вашем случае.