Add basic image info API

pull/653/merge
Varun Patil 2023-05-08 14:07:12 -07:00
parent 4aaacdda0d
commit 5149ef94d4
5 changed files with 123 additions and 36 deletions

View File

@ -39,7 +39,7 @@ public class MainActivity extends AppCompatActivity {
@Override @Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
if (request.getUrl().getHost().equals("127.0.0.1")) { if (request.getUrl().getHost().equals("127.0.0.1")) {
return mNativeX.handleRequest(request.getUrl().getPath()); return mNativeX.handleRequest(request);
} }
return null; return null;
} }

View File

@ -9,6 +9,7 @@ import android.util.Log;
import android.view.View; import android.view.View;
import android.view.Window; import android.view.Window;
import android.webkit.JavascriptInterface; import android.webkit.JavascriptInterface;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse; import android.webkit.WebResourceResponse;
import android.webkit.WebView; import android.webkit.WebView;
@ -33,47 +34,27 @@ public class NativeX {
mQuery = new TimelineQuery(activity); mQuery = new TimelineQuery(activity);
} }
public WebResourceResponse handleRequest(final String path) { public WebResourceResponse handleRequest(final WebResourceRequest request) {
byte[] bytes = null; final String path = request.getUrl().getPath();
String mimeType = "application/json";
WebResourceResponse response;
try { try {
// Match the path using regex if (request.getMethod().equals("GET")) {
String[] parts = path.split("/"); response = routerGet(path);
} else if (request.getMethod().equals("OPTIONS")) {
if (path.matches("^/image/preview/\\d+$")) { response = new WebResourceResponse("text/plain", "UTF-8", new ByteArrayInputStream("".getBytes()));
// Preview Image
bytes = mImageService.getPreview(Long.parseLong(parts[3]));
mimeType = "image/jpeg";
} else if (path.matches("^/image/full/\\d+$")) {
// Full sized image
bytes = mImageService.getFull(Long.parseLong(parts[3]));
mimeType = "image/jpeg";
} else if (path.matches("^/api/days$")) {
// Days list
bytes = mQuery.getDays().toString().getBytes();
} else if (path.matches("/api/days/\\d+$")) {
// Single day photos
bytes = mQuery.getByDayId(Long.parseLong(parts[3])).toString().getBytes();
} else { } else {
Log.e(TAG, "handleRequest: Unknown path: " + path); throw new Exception("Method Not Allowed");
} }
} catch (Exception e) { } catch (Exception e) {
Log.e(TAG, "handleRequest: ", e); Log.e(TAG, "handleRequest: ", e);
} response = makeErrorResponse();
// Construct the response
WebResourceResponse response;
if (bytes != null) {
response = new WebResourceResponse(mimeType, "UTF-8", new ByteArrayInputStream(bytes));
} else {
response = new WebResourceResponse(mimeType, "UTF-8", new ByteArrayInputStream("{}".getBytes()));
response.setStatusCodeAndReasonPhrase(500, "Internal Server Error");
} }
// Allow CORS from all origins // Allow CORS from all origins
Map<String, String> headers = new ArrayMap<>(); Map<String, String> headers = new ArrayMap<>();
headers.put("Access-Control-Allow-Origin", "*"); headers.put("Access-Control-Allow-Origin", "*");
headers.put("Access-Control-Allow-Headers", "*");
response.setResponseHeaders(headers); response.setResponseHeaders(headers);
return response; return response;
@ -100,4 +81,40 @@ public class NativeX {
window.getDecorView().setSystemUiVisibility(isDark ? 0 : View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); window.getDecorView().setSystemUiVisibility(isDark ? 0 : View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
} }
} }
protected WebResourceResponse routerGet(final String path) throws Exception {
String[] parts = path.split("/");
if (path.matches("^/image/preview/\\d+$")) {
return makeResponse(mImageService.getPreview(Long.parseLong(parts[3])), "image/jpeg");
} else if (path.matches("^/image/full/\\d+$")) {
return makeResponse(mImageService.getFull(Long.parseLong(parts[3])), "image/jpeg");
} else if (path.matches("^/image/info/\\d+$")) {
return makeResponse(mQuery.getImageInfo(Long.parseLong(parts[3])));
} else if (path.matches("^/api/days$")) {
return makeResponse(mQuery.getDays());
} else if (path.matches("/api/days/\\d+$")) {
return makeResponse(mQuery.getByDayId(Long.parseLong(parts[3])));
}
throw new Exception("Not Found");
}
protected WebResourceResponse makeResponse(byte[] bytes, String mimeType) {
if (bytes != null) {
return new WebResourceResponse(mimeType, "UTF-8", new ByteArrayInputStream(bytes));
}
return makeErrorResponse();
}
protected WebResourceResponse makeResponse(Object json) {
return makeResponse(json.toString().getBytes(), "application/json");
}
protected WebResourceResponse makeErrorResponse() {
WebResourceResponse response = new WebResourceResponse("application/json", "UTF-8", new ByteArrayInputStream("{}".getBytes()));
response.setStatusCodeAndReasonPhrase(500, "Internal Server Error");
return response;
}
} }

View File

@ -6,7 +6,7 @@ import android.database.sqlite.SQLiteOpenHelper;
public class DbService extends SQLiteOpenHelper { public class DbService extends SQLiteOpenHelper {
public DbService(Context context) { public DbService(Context context) {
super(context, "memories", null, 11); super(context, "memories", null, 16);
} }
public void onCreate(SQLiteDatabase db) { public void onCreate(SQLiteDatabase db) {

View File

@ -6,7 +6,6 @@ import android.graphics.Bitmap;
import android.provider.MediaStore; import android.provider.MediaStore;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException;
public class ImageService { public class ImageService {
Context mCtx; Context mCtx;

View File

@ -150,6 +150,76 @@ public class TimelineQuery {
} }
} }
public JSONObject getImageInfo(final long id) throws Exception {
// Get image info from DB
try (Cursor cursor = mDb.rawQuery(
"SELECT local_id, date_taken, dayid FROM images WHERE local_id = ?",
new String[] { Long.toString(id) }
)) {
if (!cursor.moveToNext()) {
throw new Exception("Image not found");
}
final long localId = cursor.getLong(0);
final long dateTaken = cursor.getLong(1);
final long dayid = cursor.getLong(2);
// All external storage images
Uri collection = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
// Same fields as server response
String[] projection = new String[] {
MediaStore.Images.Media._ID,
MediaStore.Images.Media.DISPLAY_NAME,
MediaStore.Images.Media.MIME_TYPE,
MediaStore.Images.Media.HEIGHT,
MediaStore.Images.Media.WIDTH,
MediaStore.Images.Media.SIZE,
};
// Filter for given day
String selection = MediaStore.Images.Media._ID
+ " = " + localId;
try (Cursor cursor2 = mCtx.getContentResolver().query(
collection,
projection,
selection,
null,
null
)) {
int idColumn = cursor2.getColumnIndexOrThrow(MediaStore.Images.Media._ID);
int nameColumn = cursor2.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME);
int mimeColumn = cursor2.getColumnIndexOrThrow(MediaStore.Images.Media.MIME_TYPE);
int heightColumn = cursor2.getColumnIndexOrThrow(MediaStore.Images.Media.HEIGHT);
int widthColumn = cursor2.getColumnIndexOrThrow(MediaStore.Images.Media.WIDTH);
int sizeColumn = cursor2.getColumnIndexOrThrow(MediaStore.Images.Media.SIZE);
if (!cursor2.moveToNext()) {
throw new Exception("Image not found");
}
long id2 = cursor2.getLong(idColumn);
String name = cursor2.getString(nameColumn);
String mime = cursor2.getString(mimeColumn);
long height = cursor2.getLong(heightColumn);
long width = cursor2.getLong(widthColumn);
long size = cursor2.getLong(sizeColumn);
return new JSONObject()
.put("fileid", id2)
.put("basename", name)
.put("mimetype", mime)
.put("dayid", dayid)
.put("datetaken", dateTaken)
.put("h", height)
.put("w", width)
.put("size", size)
.put("permissions", "D");
}
}
}
protected void fullSyncDb() { protected void fullSyncDb() {
Uri collection = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; Uri collection = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
@ -211,13 +281,14 @@ public class TimelineQuery {
} }
// This will use whatever is available // This will use whatever is available
final long dayId = dateTaken / 86400000; dateTaken /= 1000;
final long dayId = dateTaken / 86400;
// Delete file with same local_id and insert new one // Delete file with same local_id and insert new one
mDb.beginTransaction(); mDb.beginTransaction();
mDb.execSQL("DELETE FROM images WHERE local_id = ?", new Object[] { id }); mDb.execSQL("DELETE FROM images WHERE local_id = ?", new Object[] { id });
mDb.execSQL("INSERT OR IGNORE INTO images (local_id, mtime, basename, dayid) VALUES (?, ?, ?, ?)", mDb.execSQL("INSERT OR IGNORE INTO images (local_id, mtime, basename, date_taken, dayid) VALUES (?, ?, ?, ?, ?)",
new Object[] { id, mtime, name, dayId }); new Object[] { id, mtime, name, dateTaken, dayId });
mDb.setTransactionSuccessful(); mDb.setTransactionSuccessful();
mDb.endTransaction(); mDb.endTransaction();