Add basic image info API
parent
4aaacdda0d
commit
5149ef94d4
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue