package de.clkl.android.miniofotoapp; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; import android.util.Log; import android.view.View; import android.widget.ImageView; import android.widget.Toast; import androidx.activity.result.ActivityResult; import androidx.activity.result.ActivityResultCallback; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import androidx.core.content.FileProvider; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import java.io.File; import java.io.IOException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; import io.minio.BucketExistsArgs; import io.minio.ListObjectsArgs; import io.minio.MakeBucketArgs; import io.minio.MinioClient; import io.minio.Result; import io.minio.UploadObjectArgs; import io.minio.errors.ErrorResponseException; import io.minio.errors.InsufficientDataException; import io.minio.errors.InternalException; import io.minio.errors.InvalidResponseException; import io.minio.errors.MinioException; import io.minio.errors.ServerException; import io.minio.errors.XmlParserException; import io.minio.messages.Item; public class MainActivity extends AppCompatActivity { static final int REQUEST_IMAGE_CAPTURE = 1; public static final String TAG = "DEMO"; private ImageView thumb; private String currentPhotoPath; private MinioClient minio; private String bucket; private ActivityResultLauncher photoLauncher; private RecyclerView objectList; private ArrayList objectNames; private ObjectListAdapter objectListAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); thumb = findViewById(R.id.imageView); // list of all objects in bucket objectList = findViewById(R.id.objectList); objectNames = new ArrayList<>(); objectListAdapter = new ObjectListAdapter(objectNames); objectList.setAdapter(objectListAdapter); objectList.setLayoutManager(new LinearLayoutManager(this)); minio = MinioClient.builder() .endpoint(getString(R.string.minio_host)) .credentials(getString(R.string.minio_access_key), getString(R.string.minio_secret_key)) .build(); bucket = getString(R.string.minio_bucket); checkOrCreateBucket(minio, bucket); photoLauncher = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> { // new ActivityResultCallback() { if (result.getResultCode() == RESULT_OK) { handlePhotoCallback(); } }); listObjects(); } private void listObjects() { Runnable listObjects = new Runnable() { @Override public void run() { Iterable> objects = minio.listObjects(ListObjectsArgs.builder().bucket(bucket).prefix("Photos/").build()); objectNames.clear(); for (Result object : objects) { try { Item item = object.get(); objectNames.add(item.objectName()); Log.i(TAG, "list: '" + item.objectName() + "' is dir?: "+ item.isDir()); } catch (InvalidKeyException | IOException | NoSuchAlgorithmException | MinioException e) { e.printStackTrace(); Log.e(TAG, "something went wrong with minio", e); } } runOnUiThread(() -> { objectListAdapter.notifyDataSetChanged(); }); } }; new Thread(listObjects).start(); } private static void checkOrCreateBucket(MinioClient client, String bucket) { Runnable check = () -> { // lambda syntax: short for `new Runnable{}` // network IO is not allowed in UI-Thread, needs to be run separately try { boolean isPresent = client.bucketExists(BucketExistsArgs.builder().bucket(bucket).build()); if (!isPresent) { System.out.println("Create Bucket '" + bucket + "'"); client.makeBucket(MakeBucketArgs.builder().bucket(bucket).build()); } else { System.out.println("Bucket '" + bucket + "' already present"); } } catch (InvalidKeyException | IOException | NoSuchAlgorithmException | MinioException e) { e.printStackTrace(); Log.e(TAG, "something went wrong with minio", e); } }; // here, we just start a new Thread. Better: use a service with an interface for separation of concerns new Thread(check).start(); } private void dispatchTakePictureIntent() { Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (takePictureIntent.resolveActivity(getPackageManager()) != null) { File photoFile = null; try { photoFile = createImageFile(); } catch (IOException e) { e.printStackTrace(); Log.e(TAG, "error creating photo file", e); } if (photoFile != null) { Uri photoURI = FileProvider.getUriForFile( this, "de.clkl.android.MinioPhotoApp.fileprovider", photoFile); takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI); photoLauncher.launch(takePictureIntent); } } } private File createImageFile() throws IOException { String timeStamp = new SimpleDateFormat( "yyyy-MM-dd_HH-mm-ss", Locale.getDefault() ).format(new Date()); String fileName = "JPEG_" + timeStamp + "_"; File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES); File image = File.createTempFile( fileName, ".jpg", storageDir ); currentPhotoPath = image.getAbsolutePath(); Toast.makeText(this, currentPhotoPath, Toast.LENGTH_LONG).show(); return image; } @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { if (requestCode != REQUEST_IMAGE_CAPTURE) { super.onActivityResult(requestCode, resultCode, data); } if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) { handlePhotoCallback(); } } private void handlePhotoCallback() { thumb.setImageURI(Uri.fromFile(new File(currentPhotoPath))); Runnable upload = () -> { try { String filename = "Photos/" + currentPhotoPath.substring(currentPhotoPath.lastIndexOf("/")); minio.uploadObject(UploadObjectArgs.builder().bucket(bucket).object(filename).filename(currentPhotoPath).build()); } catch (InvalidKeyException | IOException | NoSuchAlgorithmException | MinioException e) { e.printStackTrace(); Log.e(TAG, "something went wrong with minio", e); } }; new Thread(upload).start(); listObjects(); } public void onButtonClick(View view) { Log.d(TAG, "button has been clicked"); dispatchTakePictureIntent(); } }