Store Profile Picture on AWS

Save the profile picture to AWS so that the user need not retrieve it every time.
This commit is contained in:
NMerz 2020-11-29 15:19:10 -05:00
parent bede2fc1a0
commit 70195632f8
7 changed files with 254 additions and 5 deletions

View File

@ -0,0 +1,34 @@
import java.sql.ResultSet;
import java.sql.SQLException;
public class Picture {
String base64EncodedImage;
public Picture(ResultSet rs) {
try {
this.base64EncodedImage = rs.getString("base64image");
} catch (SQLException throwables) {
throwables.printStackTrace();
this.base64EncodedImage = null;
}
}
public Picture(String base64EncodedImage) {
this.base64EncodedImage = base64EncodedImage;
}
@Override
public String toString() {
return "Picture{" +
"base64EncodedImage='" + base64EncodedImage + '\'' +
'}';
}
public String getBase64EncodedImage() {
return base64EncodedImage;
}
public void setBase64EncodedImage(String base64EncodedImage) {
this.base64EncodedImage = base64EncodedImage;
}
}

View File

@ -0,0 +1,12 @@
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import java.util.Map;
public class PictureGET implements RequestHandler<Map<String,Object>, Object> {
public Object handleRequest(Map<String, Object> inputMap, Context unfilled) {
return BasicHandler.handleRequest(inputMap, unfilled, PictureGetter.class);
}
}

View File

@ -0,0 +1,34 @@
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
public class PictureGetter implements CallHandler {
private final Connection connection;
private final String cognitoID;
private final String GET_ITEM = "SELECT * FROM Pictures WHERE cognitoID = ?;";
public PictureGetter(Connection connection, String cognitoID) {
this.connection = connection;
this.cognitoID = cognitoID;
}
@Override
public Object conductAction(Map<String, Object> bodyMap, HashMap<String, String> queryMap, String cognitoID) throws SQLException {
PreparedStatement statement = connection.prepareStatement(GET_ITEM);
if (!queryMap.get("id").toString().equals("profile")) {
throw new IllegalArgumentException("Only profile pictures are currently supported.");
}
statement.setString(1, cognitoID);
System.out.println(statement);
ResultSet queryResults = statement.executeQuery();
queryResults.first();
System.out.println(queryResults);
Picture retrievedPicture = new Picture(queryResults);
// System.out.println(retrievedPicture);
return retrievedPicture;
}
}

View File

@ -0,0 +1,11 @@
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import java.util.Map;
public class PicturePUT implements RequestHandler<Map<String,Object>, Object> {
public Object handleRequest(Map<String, Object> inputMap, Context unfilled) {
return BasicHandler.handleRequest(inputMap, unfilled, PicturePutter.class);
}
}

View File

@ -0,0 +1,28 @@
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
public class PicturePutter implements CallHandler {
private Connection connection;
private String cognitoID;
public PicturePutter(Connection connection, String cognitoID) {
this.connection = connection;
this.cognitoID = cognitoID;
}
final private String STORE_PICTURE_SQL = "REPLACE INTO Pictures(cognitoID, base64image) VALUES(?, ?);";
public Object conductAction(Map<String, Object> bodyMap, HashMap<String, String> queryString, String cognitoID) throws SQLException {
PreparedStatement storePicture = connection.prepareStatement(STORE_PICTURE_SQL);
storePicture.setString(1, cognitoID);
storePicture.setString(2, bodyMap.get("base64EncodedImage").toString());
System.out.println(storePicture);
storePicture.executeUpdate();
connection.commit();
return null;
}
}

View File

@ -1,12 +1,16 @@
package com.example.listify;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.provider.MediaStore;
import android.util.Base64;
import android.util.Base64OutputStream;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
@ -24,12 +28,12 @@ import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import com.amplifyframework.auth.AuthException;
import com.example.listify.data.List;
import com.example.listify.data.Picture;
import com.example.listify.ui.LoginPage;
import com.google.android.material.navigation.NavigationView;
import org.json.JSONException;
import java.io.File;
import java.io.IOException;
import java.io.*;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.Date;
@ -169,9 +173,22 @@ public class MainActivity extends AppCompatActivity implements CreateListDialogF
TextView emailView = navigationView.getHeaderView(0).findViewById(R.id.textViewEmailSidebar);
emailView.setText(am.getEmail());
ImageView profilePicture = navigationView.getHeaderView(0).findViewById(R.id.imageViewProfilePicture);
profilePicture.setOnClickListener(new View.OnClickListener() {
Properties configs = new Properties();
try {
configs = AuthManager.loadProperties(this, "android.resource://" + getPackageName() + "/raw/auths.json");
} catch (IOException | JSONException e) {
e.printStackTrace();
}
Requestor requestor = new Requestor(am, configs.getProperty("apiKey"));
SynchronousReceiver<Picture> profilePictureReceiver = new SynchronousReceiver<>();
ImageView profilePictureView = navigationView.getHeaderView(0).findViewById(R.id.imageViewProfilePicture);
try {
requestor.getObject("profile", Picture.class, profilePictureReceiver);
profilePictureView.setImageURI(Uri.fromFile(saveImage(profilePictureReceiver.await().getBase64EncodedImage())));
} catch (Exception e) {
e.printStackTrace();
}
profilePictureView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@ -223,27 +240,116 @@ public class MainActivity extends AppCompatActivity implements CreateListDialogF
});
}
//From: https://stackoverflow.com/questions/30005815/convert-encoded-base64-image-to-file-object-in-android
private File saveImage(final String imageData) throws IOException {
final byte[] imgBytesData = android.util.Base64.decode(imageData,
android.util.Base64.DEFAULT);
final File file = File.createTempFile("profilePicture", null, this.getCacheDir());
final FileOutputStream fileOutputStream;
try {
fileOutputStream = new FileOutputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
fileOutputStream);
try {
bufferedOutputStream.write(imgBytesData);
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
try {
bufferedOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return file;
}
protected void onActivityResult (int requestCode,
int resultCode,
Intent data) {
Uri selectedImage = null;
Properties configs = new Properties();
try {
configs = AuthManager.loadProperties(this, "android.resource://" + getPackageName() + "/raw/auths.json");
} catch (IOException | JSONException e) {
e.printStackTrace();
}
Requestor requestor = new Requestor(am, configs.getProperty("apiKey"));
switch (requestCode){
case CAMERA_CAPTURE:
Log.i("Profile Picture", "Pulling image file at " + this.newImageFileLocation.getAbsolutePath());
selectedImage = Uri.fromFile(this.newImageFileLocation);
try {
requestor.putObject(new Picture(fileToString(this.newImageFileLocation)));
} catch (JSONException | IOException jsonException) {
jsonException.printStackTrace();
}
break;
case IMAGE_SELECT:
if ((data == null) || (data.getData() == null)) {
return;
}
selectedImage = data.getData();
try {
requestor.putObject(new Picture(fileToString(new File(getRealPathFromUri(this, selectedImage)))));
} catch (JSONException | IOException exception) {
exception.printStackTrace();
}
break;
}
MainActivity.super.onActivityResult(requestCode, resultCode, data);
if (selectedImage == null) {
return;
}
NavigationView navigationView = findViewById(R.id.nav_view);
ImageView profilePicture = navigationView.getHeaderView(0).findViewById(R.id.imageViewProfilePicture);
profilePicture.setImageURI(selectedImage);
}
//From: https://stackoverflow.com/questions/20028319/how-to-convert-content-media-external-images-media-y-to-file-storage-sdc
private static String getRealPathFromUri(Context context, Uri contentUri) {
Cursor cursor = null;
try {
String[] proj = { MediaStore.Images.Media.DATA };
cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
} finally {
if (cursor != null) {
cursor.close();
}
}
}
//From: https://stackoverflow.com/questions/27784230/convert-a-file-100mo-in-base64-on-android
private String fileToString(File toStringify) throws IOException {
InputStream inputStream = new FileInputStream(toStringify.getAbsolutePath());
byte[] buffer = new byte[8192];
int bytesRead;
ByteArrayOutputStream output = new ByteArrayOutputStream();
Base64OutputStream output64 = new Base64OutputStream(output, Base64.DEFAULT);
try {
while ((bytesRead = inputStream.read(buffer)) != -1) {
output64.write(buffer, 0, bytesRead);
}
} catch (IOException e) {
e.printStackTrace();
}
output64.close();
return output.toString();
}
//getOutputImageFile from https://developer.android.com/guide/topics/media/camera

View File

@ -0,0 +1,24 @@
package com.example.listify.data;
public class Picture {
String base64EncodedImage;
public Picture(String base64EncodedImage) {
this.base64EncodedImage = base64EncodedImage;
}
@Override
public String toString() {
return "Picture{" +
"base64EncodedImage='" + base64EncodedImage + '\'' +
'}';
}
public String getBase64EncodedImage() {
return base64EncodedImage;
}
public void setBase64EncodedImage(String base64EncodedImage) {
this.base64EncodedImage = base64EncodedImage;
}
}