I am currently developing an application for Android and wanted to know how to detect a screenshot. I tried with FileObserver but the problem is that all events are detected ( when device goes into sleep, message, etc. ) . How to detect only screenshot ?
Thank you in advance !
How did you use FileObserver to detect screen shot creation? When using FileObserver, only monitor the file creation event in screen shot directory.
String path = Environment.getExternalStorageDirectory()
+ File.separator + Environment.DIRECTORY_PICTURES
+ File.separator + "Screenshots" + File.separator;
Log.d(TAG, path);
FileObserver fileObserver = new FileObserver(path, FileObserver.CREATE) {
#Override
public void onEvent(int event, String path) {
Log.d(TAG, event + " " + path);
}
};
fileObserver.startWatching();
Don't forget to declare corresponding permissions to access content in SD card.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Another solution to detect the screen shot is using ContentObserver, because there will be a record inserted to the system media database after screen shot. Following is the code snippet using ContentObserver to monitor the event. By using ContentObserver, it's not necessary to declare write/read external storage permissions, but you have to do some filters on the file name to make sure it's a screen shot event.
HandlerThread handlerThread = new HandlerThread("content_observer");
handlerThread.start();
final Handler handler = new Handler(handlerThread.getLooper()) {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
getContentResolver().registerContentObserver(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
true,
new ContentObserver(handler) {
#Override
public boolean deliverSelfNotifications() {
Log.d(TAG, "deliverSelfNotifications");
return super.deliverSelfNotifications();
}
#Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
}
#Override
public void onChange(boolean selfChange, Uri uri) {
Log.d(TAG, "onChange " + uri.toString());
if (uri.toString().matches(MediaStore.Images.Media.EXTERNAL_CONTENT_URI.toString() + "/[0-9]+")) {
Cursor cursor = null;
try {
cursor = getContentResolver().query(uri, new String[] {
MediaStore.Images.Media.DISPLAY_NAME,
MediaStore.Images.Media.DATA
}, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
final String fileName = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME));
final String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
// TODO: apply filter on the file name to ensure it's screen shot event
Log.d(TAG, "screen shot added " + fileName + " " + path);
}
} finally {
if (cursor != null) {
cursor.close();
}
}
}
super.onChange(selfChange, uri);
}
}
);
Updated
If you use second method, you have to request READ_EXTERNAL_STORAGE after version Android M, otherwise it will throw SecurityException. For more information how to request runtime permission, refer here.
I have improve the code from alijandro's comment to make it easy-to-use class and fix the problem when content observer has detect the image from camera (should be screenshot image only). Then wrap it to delegate class for convenient to use.
• ScreenshotDetectionDelegate.java
public class ScreenshotDetectionDelegate {
private WeakReference<Activity> activityWeakReference;
private ScreenshotDetectionListener listener;
public ScreenshotDetectionDelegate(Activity activityWeakReference, ScreenshotDetectionListener listener) {
this.activityWeakReference = new WeakReference<>(activityWeakReference);
this.listener = listener;
}
public void startScreenshotDetection() {
activityWeakReference.get()
.getContentResolver()
.registerContentObserver(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, true, contentObserver);
}
public void stopScreenshotDetection() {
activityWeakReference.get().getContentResolver().unregisterContentObserver(contentObserver);
}
private ContentObserver contentObserver = new ContentObserver(new Handler()) {
#Override
public boolean deliverSelfNotifications() {
return super.deliverSelfNotifications();
}
#Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
}
#Override
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
if (isReadExternalStoragePermissionGranted()) {
String path = getFilePathFromContentResolver(activityWeakReference.get(), uri);
if (isScreenshotPath(path)) {
onScreenCaptured(path);
}
} else {
onScreenCapturedWithDeniedPermission();
}
}
};
private void onScreenCaptured(String path) {
if (listener != null) {
listener.onScreenCaptured(path);
}
}
private void onScreenCapturedWithDeniedPermission() {
if (listener != null) {
listener.onScreenCapturedWithDeniedPermission();
}
}
private boolean isScreenshotPath(String path) {
return path != null && path.toLowerCase().contains("screenshots");
}
private String getFilePathFromContentResolver(Context context, Uri uri) {
try {
Cursor cursor = context.getContentResolver().query(uri, new String[]{
MediaStore.Images.Media.DISPLAY_NAME,
MediaStore.Images.Media.DATA
}, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
cursor.close();
return path;
}
} catch (IllegalStateException ignored) {
}
return null;
}
private boolean isReadExternalStoragePermissionGranted() {
return ContextCompat.checkSelfPermission(activityWeakReference.get(), Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
}
public interface ScreenshotDetectionListener {
void onScreenCaptured(String path);
void onScreenCapturedWithDeniedPermission();
}
}
• ScreenshotDetectionActivity.java
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.widget.Toast;
public abstract class ScreenshotDetectionActivity extends AppCompatActivity implements ScreenshotDetectionDelegate.ScreenshotDetectionListener {
private static final int REQUEST_CODE_READ_EXTERNAL_STORAGE_PERMISSION = 3009;
private ScreenshotDetectionDelegate screenshotDetectionDelegate = new ScreenshotDetectionDelegate(this, this);
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
checkReadExternalStoragePermission();
}
#Override
protected void onStart() {
super.onStart();
screenshotDetectionDelegate.startScreenshotDetection();
}
#Override
protected void onStop() {
super.onStop();
screenshotDetectionDelegate.stopScreenshotDetection();
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE_READ_EXTERNAL_STORAGE_PERMISSION:
if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
showReadExternalStoragePermissionDeniedMessage();
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
#Override
public void onScreenCaptured(String path) {
// Do something when screen was captured
}
#Override
public void onScreenCapturedWithDeniedPermission() {
// Do something when screen was captured but read external storage permission has denied
}
private void checkReadExternalStoragePermission() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
requestReadExternalStoragePermission();
}
}
private void requestReadExternalStoragePermission() {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_CODE_READ_EXTERNAL_STORAGE_PERMISSION);
}
private void showReadExternalStoragePermissionDeniedMessage() {
Toast.makeText(this, "Read external storage permission has denied", Toast.LENGTH_SHORT).show();
}
}
• MainActivity.java
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends ScreenshotDetectionActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public void onScreenCaptured(String path) {
Toast.make(this, path, Toast.LENGTH_SHORT).show();
}
#Override
public void onScreenCapturedWithDeniedPermission() {
Toast.make(this, "Please grant read external storage permission for screenshot detection", Toast.LENGTH_SHORT).show();
}
}
You can create FileObserver that only monitors screenshot directory plus only trigger events for file or directory creation.
For more information click here.
I made a git project for Android screenshot detection using Content Observer.
It is working fine from API 14 to the most recent version (at the time of posting).
1.ScreenShotContentObserver .class
(original screenshot delete -> inform screenshot taken and give screenshot bitmap )
public class ScreenShotContentObserver extends ContentObserver {
private final String TAG = this.getClass().getSimpleName();
private static final String[] PROJECTION = new String[]{
MediaStore.Images.Media.DISPLAY_NAME, MediaStore.Images.Media.DATA,
MediaStore.Images.Media.DATE_ADDED, MediaStore.Images.ImageColumns._ID
};
private static final long DEFAULT_DETECT_WINDOW_SECONDS = 10;
private static final String SORT_ORDER = MediaStore.Images.Media.DATE_ADDED + " DESC";
public static final String FILE_POSTFIX = "FROM_ASS";
private static final String WATERMARK = "Scott";
private ScreenShotListener mListener;
private ContentResolver mContentResolver;
private String lastPath;
public ScreenShotContentObserver(Handler handler, ContentResolver contentResolver, ScreenShotListener listener) {
super(handler);
mContentResolver = contentResolver;
mListener = listener;
}
#Override
public boolean deliverSelfNotifications() {
Log.e(TAG, "deliverSelfNotifications");
return super.deliverSelfNotifications();
}
#Override
synchronized public void onChange(boolean selfChange) {
super.onChange(selfChange);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
//above API 16 Pass~!(duplicated call...)
return;
}
Log.e(TAG, "[Start] onChange : " + selfChange);
try {
process(MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
Log.e(TAG, "[Finish] general");
} catch (Exception e) {
Log.e(TAG, "[Finish] error : " + e.toString(), e);
}
}
#Override
synchronized public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
Log.e(TAG, "[Start] onChange : " + selfChange + " / uri : " + uri.toString());
if (uri.toString().startsWith(MediaStore.Images.Media.EXTERNAL_CONTENT_URI.toString())) {
try {
process(uri);
Log.e(TAG, "[Finish] general");
} catch (Exception e) {
Log.e(TAG, "[Finish] error : " + e.toString(), e);
}
} else {
Log.e(TAG, "[Finish] not EXTERNAL_CONTENT_URI ");
}
}
public void register() {
Log.d(TAG, "register");
mContentResolver.registerContentObserver(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, true, this);
}
public void unregister() {
Log.d(TAG, "unregister");
mContentResolver.unregisterContentObserver(this);
}
private boolean process(Uri uri) throws Exception {
Data result = getLatestData(uri);
if (result == null) {
Log.e(TAG, "[Result] result is null!!");
return false;
}
if (lastPath != null && lastPath.equals(result.path)) {
Log.e(TAG, "[Result] duplicate!!");
return false;
}
long currentTime = System.currentTimeMillis() / 1000;
if (matchPath(result.path) && matchTime(currentTime, result.dateAdded)) {
lastPath = result.path;
Uri screenUri = Uri.parse(MediaStore.Images.Media.EXTERNAL_CONTENT_URI.toString() + "/" + result.id);
Log.e(TAG, "[Result] This is screenshot!! : " + result.fileName + " | dateAdded : " + result.dateAdded + " / " + currentTime);
Bitmap bitmap = MediaStore.Images.Media.getBitmap(mContentResolver, screenUri);
Bitmap copyBitmap = bitmap.copy(bitmap.getConfig(), true);
bitmap.recycle();
int temp = mContentResolver.delete(screenUri, null, null);
Log.e(TAG, "Delete Result : " + temp);
if (mListener != null) {
mListener.onScreenshotTaken(copyBitmap, result.fileName);
}
return true;
} else {
Log.e(TAG, "[Result] No ScreenShot : " + result.fileName);
}
return false;
}
private Data getLatestData(Uri uri) throws Exception {
Data data = null;
Cursor cursor = null;
try {
cursor = mContentResolver.query(uri, PROJECTION, null, null, SORT_ORDER);
if (cursor != null && cursor.moveToFirst()) {
long id = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.ImageColumns._ID));
String fileName = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME));
String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
long dateAdded = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media.DATE_ADDED));
if (fileName.contains(FILE_POSTFIX)) {
if (cursor.moveToNext()) {
id = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.ImageColumns._ID));
fileName = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME));
path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
dateAdded = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media.DATE_ADDED));
} else {
return null;
}
}
data = new Data();
data.id = id;
data.fileName = fileName;
data.path = path;
data.dateAdded = dateAdded;
Log.e(TAG, "[Recent File] Name : " + fileName);
}
} finally {
if (cursor != null) {
cursor.close();
}
}
return data;
}
private boolean matchPath(String path) {
return (path.toLowerCase().contains("screenshots/") && !path.contains(FILE_POSTFIX));
}
private boolean matchTime(long currentTime, long dateAdded) {
return Math.abs(currentTime - dateAdded) <= DEFAULT_DETECT_WINDOW_SECONDS;
}
class Data {
long id;
String fileName;
String path;
long dateAdded;
}
}
Util.class
public static void saveImage(Context context, Bitmap bitmap, String title) throws Exception {
OutputStream fOut = null;
title = title.replaceAll(" ", "+");
int index = title.lastIndexOf(".png");
String fileName = title.substring(0, index) + ScreenShotContentObserver.FILE_POSTFIX + ".png";
final String appDirectoryName = "Screenshots";
final File imageRoot = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), appDirectoryName);
imageRoot.mkdirs();
final File file = new File(imageRoot, fileName);
fOut = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut);
fOut.flush();
fOut.close();
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, "XXXXX");
values.put(MediaStore.Images.Media.DESCRIPTION, "description here");
values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis());
values.put(MediaStore.Images.ImageColumns.BUCKET_ID, file.hashCode());
values.put(MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME, file.getName());
values.put("_data", file.getAbsolutePath());
ContentResolver cr = context.getContentResolver();
Uri newUri = cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, newUri));
}
Related
hey guys I am creating a WhatsApp sticker app that fetch stickers from Firebase cloud Firestore and display it into recycler view. Each recycler view contains list of stickers from each sticker pack. On clicking recycler view I am storing the images from firebase into my app external directory but I dont know how to expose these stickers that are stored inside my app directory to WhatsApp. I tried creating Json file and stored it inside the same directory where I have stored my stickers but it was of no use. I am stuck on what to do next. I am sharing the code that I have tried. Any help is highly appreciated.
MainActivity.java:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FirebaseFirestore db = FirebaseFirestore.getInstance();
CollectionReference stickerPacksRef = db.collection("stickers_pack");
RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
stickerPacksRef.get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
List<StickerPacks> stickerPacks = new ArrayList<>();
for (DocumentSnapshot documentSnapshot : queryDocumentSnapshots) {
String name = documentSnapshot.getString("name");
List<String> stickerUrls = (List<String>) documentSnapshot.get("stickers");
StickerPacks stickerPack = new StickerPacks(name, stickerUrls);
stickerPacks.add(stickerPack);
}
StickerPacksAdapter adapter = new StickerPacksAdapter(MainActivity.this, stickerPacks);
recyclerView.setAdapter(adapter);
}
});
}
}
StickerContentProvider.java:
public class StickerContentProvider extends ContentProvider {
public static final String STICKER_PACK_IDENTIFIER_IN_QUERY = "sticker_pack_identifier";
public static final String STICKER_PACK_NAME_IN_QUERY = "sticker_pack_name";
public static final String STICKER_PACK_PUBLISHER_IN_QUERY = "sticker_pack_publisher";
public static final String STICKER_PACK_ICON_IN_QUERY = "sticker_pack_icon";
public static final String ANDROID_APP_DOWNLOAD_LINK_IN_QUERY = "android_play_store_link";
public static final String IOS_APP_DOWNLOAD_LINK_IN_QUERY = "ios_app_download_link";
public static final String PUBLISHER_EMAIL = "sticker_pack_publisher_email";
public static final String PUBLISHER_WEBSITE = "sticker_pack_publisher_website";
public static final String PRIVACY_POLICY_WEBSITE = "sticker_pack_privacy_policy_website";
public static final String LICENSE_AGREENMENT_WEBSITE = "sticker_pack_license_agreement_website";
public static final String IMAGE_DATA_VERSION = "image_data_version";
public static final String AVOID_CACHE = "whatsapp_will_not_cache_stickers";
public static final String ANIMATED_STICKER_PACK = "animated_sticker_pack";
public static final String STICKER_FILE_NAME_IN_QUERY = "sticker_file_name";
public static final String STICKER_FILE_EMOJI_IN_QUERY = "sticker_emoji";
private static final String CONTENT_FILE_NAME = "contents.json";
public static final Uri AUTHORITY_URI = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(BuildConfig.CONTENT_PROVIDER_AUTHORITY).appendPath(StickerContentProvider.METADATA).build();
/**
* Do not change the values in the UriMatcher because otherwise, WhatsApp will not be able to fetch the stickers from the ContentProvider.
*/
private static final UriMatcher MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
private static final String METADATA = "metadata";
private static final int METADATA_CODE = 1;
private static final int METADATA_CODE_FOR_SINGLE_PACK = 2;
static final String STICKERS = "stickers";
private static final int STICKERS_CODE = 3;
static final String STICKERS_ASSET = "stickers_asset";
private static final int STICKERS_ASSET_CODE = 4;
private static final int STICKER_PACK_TRAY_ICON_CODE = 5;
private List<StickerPack> stickerPackList;
#Override
public boolean onCreate() {
final String authority = BuildConfig.CONTENT_PROVIDER_AUTHORITY;
if (!authority.startsWith(Objects.requireNonNull(getContext()).getPackageName())) {
throw new IllegalStateException("your authority (" + authority + ") for the content provider should start with your package name: " + getContext().getPackageName());
}
MATCHER.addURI(authority, METADATA, METADATA_CODE);
MATCHER.addURI(authority, METADATA + "/*", METADATA_CODE_FOR_SINGLE_PACK);
MATCHER.addURI(authority, STICKERS + "/*", STICKERS_CODE);
File contentsFile=new File(getContext().getExternalFilesDir(""),"Danish/"+CONTENT_FILE_NAME);
if(contentsFile.exists()) {
for (StickerPack stickerPack : getStickerPackList()) {
MATCHER.addURI(authority, STICKERS_ASSET + "/" + stickerPack.identifier + "/" + stickerPack.trayImageFile, STICKER_PACK_TRAY_ICON_CODE);
for (Sticker sticker : stickerPack.getStickers()) {
MATCHER.addURI(authority, STICKERS_ASSET + "/" + stickerPack.identifier + "/" + sticker.imageFileName, STICKERS_ASSET_CODE);
}
}
}
return true;
}
#Override
public Cursor query(#NonNull Uri uri, #Nullable String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
final int code = MATCHER.match(uri);
if (code == METADATA_CODE) {
return getPackForAllStickerPacks(uri);
} else if (code == METADATA_CODE_FOR_SINGLE_PACK) {
return getCursorForSingleStickerPack(uri);
} else if (code == STICKERS_CODE) {
return getStickersForAStickerPack(uri);
} else {
throw new IllegalArgumentException("Unknown URI: " + uri);
}
}
#Nullable
#Override
public AssetFileDescriptor openAssetFile(#NonNull Uri uri, #NonNull String mode) {
final int matchCode = MATCHER.match(uri);
if (matchCode == STICKERS_ASSET_CODE || matchCode == STICKER_PACK_TRAY_ICON_CODE) {
try {
return getImageAsset(uri);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
return null;
}
#Override
public String getType(#NonNull Uri uri) {
final int matchCode = MATCHER.match(uri);
switch (matchCode) {
case METADATA_CODE:
return "vnd.android.cursor.dir/vnd." + BuildConfig.CONTENT_PROVIDER_AUTHORITY + "." + METADATA;
case METADATA_CODE_FOR_SINGLE_PACK:
return "vnd.android.cursor.item/vnd." + BuildConfig.CONTENT_PROVIDER_AUTHORITY + "." + METADATA;
case STICKERS_CODE:
return "vnd.android.cursor.dir/vnd." + BuildConfig.CONTENT_PROVIDER_AUTHORITY + "." + STICKERS;
case STICKERS_ASSET_CODE:
return "image/webp";
case STICKER_PACK_TRAY_ICON_CODE:
return "image/png";
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
}
private synchronized void readContentFile(#NonNull Context context) {
File contentsFile=new File(context.getExternalFilesDir(""),"Danish/"+CONTENT_FILE_NAME);
if(contentsFile.exists()) {
try (FileInputStream contentsInputStream = new FileInputStream(contentsFile)) {
stickerPackList = ContentFileParser.parseStickerPacks(contentsInputStream);
} catch (IOException | IllegalStateException e) {
throw new RuntimeException(CONTENT_FILE_NAME + " file has some issues: " + e.getMessage(), e);
}
}
}
private List<StickerPack> getStickerPackList() {
if (stickerPackList == null) {
readContentFile(Objects.requireNonNull(getContext()));
}
return stickerPackList;
}
private Cursor getPackForAllStickerPacks(#NonNull Uri uri) {
return getStickerPackInfo(uri, getStickerPackList());
}
private Cursor getCursorForSingleStickerPack(#NonNull Uri uri) {
final String identifier = uri.getLastPathSegment();
for (StickerPack stickerPack : getStickerPackList()) {
if (identifier.equals(stickerPack.identifier)) {
return getStickerPackInfo(uri, Collections.singletonList(stickerPack));
}
}
return getStickerPackInfo(uri, new ArrayList<>());
}
#NonNull
private Cursor getStickerPackInfo(#NonNull Uri uri, #NonNull List<StickerPack> stickerPackList) {
MatrixCursor cursor = new MatrixCursor(
new String[]{
STICKER_PACK_IDENTIFIER_IN_QUERY,
STICKER_PACK_NAME_IN_QUERY,
STICKER_PACK_PUBLISHER_IN_QUERY,
STICKER_PACK_ICON_IN_QUERY,
ANDROID_APP_DOWNLOAD_LINK_IN_QUERY,
IOS_APP_DOWNLOAD_LINK_IN_QUERY,
PUBLISHER_EMAIL,
PUBLISHER_WEBSITE,
PRIVACY_POLICY_WEBSITE,
LICENSE_AGREENMENT_WEBSITE,
IMAGE_DATA_VERSION,
AVOID_CACHE,
ANIMATED_STICKER_PACK,
});
for (StickerPack stickerPack : stickerPackList) {
MatrixCursor.RowBuilder builder = cursor.newRow();
builder.add(stickerPack.identifier);
builder.add(stickerPack.name);
builder.add(stickerPack.publisher);
builder.add(stickerPack.trayImageFile);
builder.add(stickerPack.androidPlayStoreLink);
builder.add(stickerPack.iosAppStoreLink);
builder.add(stickerPack.publisherEmail);
builder.add(stickerPack.publisherWebsite);
builder.add(stickerPack.privacyPolicyWebsite);
builder.add(stickerPack.licenseAgreementWebsite);
builder.add(stickerPack.imageDataVersion);
builder.add(stickerPack.avoidCache ? 1 : 0);
builder.add(stickerPack.animatedStickerPack ? 1 : 0);
}
cursor.setNotificationUri(Objects.requireNonNull(getContext()).getContentResolver(), uri);
return cursor;
}
#NonNull
private Cursor getStickersForAStickerPack(#NonNull Uri uri) {
final String identifier = uri.getLastPathSegment();
MatrixCursor cursor = new MatrixCursor(new String[]{STICKER_FILE_NAME_IN_QUERY, STICKER_FILE_EMOJI_IN_QUERY});
for (StickerPack stickerPack : getStickerPackList()) {
if (identifier.equals(stickerPack.identifier)) {
for (Sticker sticker : stickerPack.getStickers()) {
cursor.addRow(new Object[]{sticker.imageFileName, TextUtils.join(",", sticker.emojis)});
}
}
}
cursor.setNotificationUri(Objects.requireNonNull(getContext()).getContentResolver(), uri);
return cursor;
}
private AssetFileDescriptor getImageAsset(Uri uri) throws IllegalArgumentException, FileNotFoundException {
AssetManager am = Objects.requireNonNull(getContext()).getAssets();
final List<String> pathSegments = uri.getPathSegments();
if (pathSegments.size() != 3) {
throw new IllegalArgumentException("path segments should be 3, uri is: " + uri);
}
String fileName = pathSegments.get(pathSegments.size() - 1);
final String identifier = pathSegments.get(pathSegments.size() - 2);
if (TextUtils.isEmpty(identifier)) {
throw new IllegalArgumentException("identifier is empty, uri: " + uri);
}
if (TextUtils.isEmpty(fileName)) {
throw new IllegalArgumentException("file name is empty, uri: " + uri);
}
//making sure the file that is trying to be fetched is in the list of stickers.
for (StickerPack stickerPack : getStickerPackList()) {
if (identifier.equals(stickerPack.identifier)) {
if (fileName.equals(stickerPack.trayImageFile)) {
return fetchFile(uri, am, fileName, identifier);
} else {
for (Sticker sticker : stickerPack.getStickers()) {
if (fileName.equals(sticker.imageFileName)) {
return fetchFile(uri, am, fileName, identifier);
}
}
}
}
}
return null;
}
private AssetFileDescriptor fetchFile(#NonNull Uri uri, #NonNull AssetManager am, #NonNull String fileName, #NonNull String identifier) throws FileNotFoundException {
final File cacheFile = getContext().getExternalFilesDir("");
final File file = new File(cacheFile, "Danish/"+fileName);
return new AssetFileDescriptor(ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY), 0, AssetFileDescriptor.UNKNOWN_LENGTH);
}
#Override
public int delete(#NonNull Uri uri, #Nullable String selection, String[] selectionArgs) {
throw new UnsupportedOperationException("Not supported");
}
#Override
public Uri insert(#NonNull Uri uri, ContentValues values) {
throw new UnsupportedOperationException("Not supported");
}
#Override
public int update(#NonNull Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
throw new UnsupportedOperationException("Not supported");
}
}
StickerPacksAdapter.java:
class StickerPacksAdapter extends RecyclerView.Adapter<StickerPacksAdapter.StickerPackViewHolder> {
private List<StickerPacks> stickerPacks;
private Context context;
public StickerPacksAdapter(Context context, List<StickerPacks> stickerPacks) {
this.context = context;
this.stickerPacks = stickerPacks;
}
#NonNull
#Override
public StickerPackViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_sticker_pack, parent, false);
return new StickerPackViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull StickerPackViewHolder holder, int position) {
StickerPacks stickerPacks = this.stickerPacks.get(position);
holder.nameTextView.setText(stickerPacks.getName());
List<String> stickerUrls = stickerPacks.getStickerUrls();
for (int i = 0; i < stickerUrls.size(); i++) {
String stickerUrl = stickerUrls.get(i);
ImageView imageView = holder.stickerImageViews[i];
if(imageView!=null)
Glide.with(holder.itemView.getContext()).load(stickerUrl).into(imageView);
}
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
List<String> stickerUrls = stickerPacks.getStickerUrls();
String stickerPackName = stickerPacks.getName();
File directory = new File(context.getExternalFilesDir(""), stickerPackName);
if (!directory.exists()) {
directory.mkdirs();
}
for (int i = 0; i < stickerUrls.size(); i++) {
String stickerUrl = stickerUrls.get(i);
String fileName = "sticker" + i + ".webp"; // you can choose your own file name
File file = new File(directory, fileName);
FirebaseStorage.getInstance().getReferenceFromUrl(stickerUrl).getDownloadUrl()
.addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
String url = uri.toString();
new AsyncTask<Void, Void, Void>() {
#SuppressLint("StaticFieldLeak")
#Override
protected Void doInBackground(Void... voids) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("Unexpected code " + response);
}
try (InputStream inputStream = response.body().byteStream()) {
FileOutputStream outputStream = new FileOutputStream(file);
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.flush();
outputStream.close();
}
JSONObject json = new JSONObject();
try {
json.put("android_play_store_link", "");
json.put("ios_app_store_link", "");
}catch (JSONException e)
{
e.printStackTrace();
}
JSONArray stickerPacks = new JSONArray();
JSONObject stickerPack = new JSONObject();
try {
stickerPack.put("identifier", stickerPackName.toLowerCase());
stickerPack.put("name", stickerPackName);
stickerPack.put("publisher", stickerPackName);
stickerPack.put("tray_image_file", "sticker0.webp");
stickerPack.put("image_data_version", "1");
stickerPack.put("avoid_cache", false);
stickerPack.put("publisher_email", "");
stickerPack.put("publisher_website", "");
stickerPack.put("privacy_policy_website", "");
stickerPack.put("license_agreement_website", "");
stickerPack.put("animated_sticker_pack", false);
} catch (JSONException e) {
e.printStackTrace();
}
JSONArray stickersArray = new JSONArray();
int i=0;
for (String stickerUrl : stickerUrls) {
JSONObject sticker = new JSONObject();
try {
sticker.put("image_file", "sticker"+i+".webp");
sticker.put("emojis", new JSONArray().put("🥰").put("😘").put("❤️"));
stickersArray.put(sticker);
i++;
} catch (JSONException e) {
e.printStackTrace();
}
}
try {
stickerPack.put("stickers", stickersArray);
stickerPacks.put(stickerPack);
json.put("sticker_packs", stickerPacks);
File file = new File(context.getExternalFilesDir("")+"/"+stickerPackName, "contents.json");
try (FileOutputStream outputStream = new FileOutputStream(file)) {
Log.d("TAG", "entered: ");
outputStream.write(json.toString().getBytes());
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
} catch (JSONException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}.execute();
}
});
}
Intent intent = new Intent();
intent.setAction("com.whatsapp.intent.action.ENABLE_STICKER_PACK");
intent.putExtra("sticker_pack_id", stickerPackName);
intent.putExtra("sticker_pack_authority", BuildConfig.CONTENT_PROVIDER_AUTHORITY);
intent.putExtra("sticker_pack_name", stickerPackName);
try {
context.startActivity(intent);
} catch (ActivityNotFoundException e) {
e.printStackTrace(); }
}
});
}
#Override
public int getItemCount() {
return stickerPacks.size();
}
public class StickerPackViewHolder extends RecyclerView.ViewHolder {
private TextView nameTextView;
private ImageView[] stickerImageViews;
public StickerPackViewHolder(#NonNull View itemView) {
super(itemView);
nameTextView = itemView.findViewById(R.id.sticker_pack_name_text_view);
stickerImageViews = new ImageView[30];
for (int i = 0; i < 4; i++) {
stickerImageViews[i] = itemView.findViewById(getStickerImageViewId(i));
}
}
private int getStickerImageViewId(int index) {
switch (index) {
case 0:
return R.id.sticker1;
case 1:
return R.id.sticker2;
case 2:
return R.id.sticker3;
case 3:
return R.id.sticker4;
// and so on, up to 30
default:
throw new IllegalArgumentException("Invalid sticker image view index: " + index);
}
}
}
}
I'm working on this project where I generated CSV files from contact list, and now I'm supposed to package all the files as a single zip archive using RxJava, so I'm trying to get the method to create an archive invoked using onComplete method. But the application is crashing with this error:
Attempt to invoke direct method 'boolean appjoe.wordpress.com.testdemo.Tab2$FileHelper.zip(java.lang.String, java.lang.String)' on a null object reference
This is my code:
path: /storage/emulated/0/Android/data/com.wordpress.appjoe/csv
File location = new File(Environment.getExternalStorageDirectory(), "Android/data/com.wordpress.appjoe/csv/");
File fileLocation;
FileOutputStream dest;
String path;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_tab2, container, false);
mbutton = v.findViewById(R.id.extractContact);
mbutton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Permission has already been granted
Observer observer = new Observer() {
#Override
public void onSubscribe(Disposable d) {
mCursor = getCursor();
fCursor = getCursor();
location.mkdirs();
path = location.getAbsolutePath();
try {
dest = new FileOutputStream(path);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
#Override
public void onNext(Object o) {
contactData = o.toString();
fCursor.moveToPosition(count);
fileLocation = new File(path, getName(fCursor)+".csv");
try {
FileOutputStream fileOut = new FileOutputStream(fileLocation);
fileOut.write(contactData.getBytes());
fileOut.flush();
fileOut.close();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onError(Throwable e) {
}
#Override
public void onComplete() {
mCursor.close();
fCursor.close();
// Creating archive once the CSV files are generated
if (fileHelper.zip(path, location.getParent())) {
Toast.makeText(getContext(), "Zip successful", Toast.LENGTH_SHORT).show();
}
Log.d("fileLocation", "location: " + location.getParent());
Log.d("fileLocation", "path: " + path);
Log.d("Observer_contact", "Completed");
}
};
io.reactivex.Observable.create(new ObservableOnSubscribe<String>() {
#Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
try {
for (count = 0; count < mCursor.getCount(); count++) {
emitter.onNext(loadContacts(count));
}
emitter.onComplete();
} catch (Exception e) {
emitter.onError(e);
}
}
}).subscribeOn(Schedulers.io())
.distinct()
.subscribeWith(observer);
}
}
});
// Inflate the layout for this fragment
return v;
}
RxJava implementation to fetch contacts:
public String loadContacts(int i) {
StringBuilder mBuilder = new StringBuilder();
ContentResolver mContentResolver = getActivity().getContentResolver();
mCursor.moveToPosition(i);
if (mCursor.getCount() > 0 ) {
String id = getID(mCursor);
String name = getName(mCursor);
int hasPhoneNumber = hasNumber(mCursor);
if (hasPhoneNumber > 0) {
mBuilder.append("\"").append(name).append("\"");
Cursor cursor = mContentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "= ?",
new String[]{id}, null);
assert cursor != null;
while (cursor.moveToNext()) {
String phoneNumber = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))
.replaceAll("\\s", "");
// if number is not existing in the list, then add number to the string
if (!(mBuilder.toString().contains(phoneNumber))) {
mBuilder.append(", ").append(phoneNumber);
}
}
cursor.close();
}
}
return mBuilder.toString();
}
Methods to get necessary information:
private Cursor getCursor() {
ContentResolver mContentResolver = getActivity().getContentResolver();
return mContentResolver.query(ContactsContract.Contacts.CONTENT_URI,
null, null, null, ContactsContract.Contacts.DISPLAY_NAME + " ASC");
}
private String getID(Cursor cursor) {
String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
return id;
}
private String getName(Cursor cursor) {
String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
return name;
}
private int hasNumber(Cursor cursor) {
return Integer.parseInt(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)));
}
Class to generate archive
// Custom class to help with zipping of generated CSVs
private class FileHelper {
private static final int BUFFER_SIZE = 2048;
private String TAG = FileHelper.class.getName();
private String parentPath = "";
private String destinationFileName = "Contacts_CSV.zip";
private boolean zip (String sourcePath, String destinationPath) {
new File(destinationPath).mkdirs();
FileOutputStream fileOutputStream;
ZipOutputStream zipOutputStream = null;
try {
if (!destinationPath.endsWith("/")) {
destinationPath = destinationPath + "/";
}
String destination = destinationPath + destinationFileName;
File file = new File(destination);
if (!file.exists()) {
file.createNewFile();
}
fileOutputStream = new FileOutputStream(file);
zipOutputStream = new ZipOutputStream(new BufferedOutputStream(fileOutputStream));
parentPath = new File(sourcePath).getParent() + "/";
zipFile(zipOutputStream, sourcePath);
} catch (IOException e) {
e.printStackTrace();
Log.d(TAG,e.getMessage());
return false;
} finally {
if (zipOutputStream!=null)
try {
zipOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return true;
}
private void zipFile (ZipOutputStream zipOutputStream, String sourcePath) throws IOException {
java.io.File files = new java.io.File(sourcePath);
java.io.File[] fileList = files.listFiles();
String entryPath="";
BufferedInputStream input;
for (java.io.File file : fileList) {
if (file.isDirectory()) {
} else {
byte data[] = new byte[BUFFER_SIZE];
FileInputStream fileInputStream = new FileInputStream(file.getPath());
input = new BufferedInputStream(fileInputStream, BUFFER_SIZE);
entryPath = file.getAbsolutePath().replace(parentPath, "");
ZipEntry entry = new ZipEntry(entryPath);
zipOutputStream.putNextEntry(entry);
int count;
while ((count = input.read(data, 0, BUFFER_SIZE)) != -1) {
zipOutputStream.write(data, 0, count);
}
input.close();
}
}
}
}
I solved this problem by removing the class FileHelper and making both the methods inside FileHelper private methods within the main class. That way, calling the methods from onComplete() didn't cause the program to crash, and it was successfully generating the zip file.
I have an android application, which function is to upload image to AWS(Amazon Web Service) S3. When I first time run this app image upload successfully. But when I upload image second time, I am getting following error. How can I fix this error?
Here is the error:
Here is my activity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// getActionBar().setDisplayShowTitleEnabled(false);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
s3Client.setRegion(Region.getRegion(Regions.US_WEST_2));
setContentView(R.layout.submit);
submit = (Button) findViewById(R.id.buttonsubmit);
submit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Uri selectedImage = Uri.parse(Environment
.getExternalStorageDirectory().getPath()
+ File.separator
+ "Pictures"
+ File.separator
+ "Spike" + File.separator + "cubicasa.jpg");
new S3PutObjectTask().execute(selectedImage);
}
});
}
private class S3PutObjectTask extends AsyncTask<Uri, Void, S3TaskResult> {
ProgressDialog dialog;
protected void onPreExecute() {
dialog = new ProgressDialog(SubmitActivity.this);
dialog.setMessage(SubmitActivity.this.getString(R.string.uploading));
dialog.setCancelable(false);
dialog.show();
}
protected S3TaskResult doInBackground(Uri... uris) {
if (uris == null || uris.length != 1) {
return null;
}
// The file location of the image selected.
String filepath = Environment.getExternalStorageDirectory()
.toString()
+ File.separator
+ "Pictures"
+ File.separator
+ "Spike" + File.separator + "cubicasa.jpg";
Uri selectedImage = Uri.fromFile(new File(filepath));
// Uri selectedImage =
// Uri.parse("content://media/external/images/media/40894");
String URLLLLLLLLL = selectedImage.toString();
Log.e("uRLLLLLLLLLLLLLL", URLLLLLLLLL);
ContentResolver resolver = getContentResolver();
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentType(resolver.getType(selectedImage));
S3TaskResult result = new S3TaskResult();
// Put the image data into S3.
try {
s3Client.createBucket(Constants.getPictureBucket());
PutObjectRequest por = new PutObjectRequest(
Constants.getPictureBucket(), Constants.PICTURE_NAME,
resolver.openInputStream(selectedImage), metadata);
s3Client.putObject(por);
} catch (Exception exception) {
result.setErrorMessage(exception.getMessage());
}
return result;
}
protected void onPostExecute(S3TaskResult result) {
dialog.dismiss();
if (result.getErrorMessage() != null) {
displayErrorAlert(
SubmitActivity.this
.getString(R.string.upload_failure_title),
result.getErrorMessage());
} else {
Toast toast = Toast.makeText(getApplicationContext(),
"Uploaded Successfully", Toast.LENGTH_SHORT);
toast.show();
}
}
}
Here is my constantclass:
public class Constants {
public static final String ACCESS_KEY_ID = "accesskey";
public static final String SECRET_KEY = "secretkey";
public static final String PICTURE_BUCKET = "picture-bucket5";
public static final String PICTURE_NAME = "NameOfThePicture5";
public static String getPictureBucket() {
return ("bd.dse.test" + ACCESS_KEY_ID + PICTURE_BUCKET).toLowerCase(Locale.US);
}
Any help will be greatly appreciated. Thanks in advance.
From your code : your are creating bucket every time, don't do like that that will cause duplicate of bucket. create bucket once with name (string) like this below code.
s3Client.createBucket("images");
from next time on wards don't call this creating bucket in your code, just put images in that bucket like this following code.
S3.createObjectForBucket("images", Token, _Image);
I was wondering whether it was possible to do such a thing. I know that one would need to modify some of the existing code to pull this off but I was wondering if anyone had any direction on where to look and how to do this.
I am placing a few custom tiles on a specific area on the map as a replacement for OSM tiles providers but need them to be stored in the /assets/ folder. Any ideas?
I use the nexts classes to do that.
import java.io.InputStream;
import org.osmdroid.ResourceProxy.string;
import org.osmdroid.tileprovider.util.StreamUtils;
import android.content.res.AssetManager;
import android.graphics.drawable.Drawable;
public class AssetsTileSource extends CustomBitmapTileSourceBase {
private final AssetManager mAssetManager;
public AssetsTileSource(final AssetManager assetManager, final String aName, final string aResourceId,
final int aZoomMinLevel, final int aZoomMaxLevel, final int aTileSizePixels,
final String aImageFilenameEnding) {
super(aName, aResourceId, aZoomMinLevel, aZoomMaxLevel, aTileSizePixels, aImageFilenameEnding);
mAssetManager = assetManager;
}
#Override
public Drawable getDrawable(final String aFilePath) {
InputStream inputStream = null;
try {
inputStream = mAssetManager.open(aFilePath);
if (inputStream != null) {
final Drawable drawable = getDrawable(inputStream);
return drawable;
}
} catch (final Throwable e) {
// Tile does not exist in assets folder.
// Ignore silently
} finally {
if (inputStream != null) {
StreamUtils.closeStream(inputStream);
}
}
return null;
}
}
MapTileFileAssetsProvider.java
public class MapTileFileAssetsProvider extends MapTileModuleProviderBase {
protected ITileSource mTileSource;
public MapTileFileAssetsProvider(final ITileSource pTileSource) {
super(OpenStreetMapTileProviderConstants.NUMBER_OF_TILE_FILESYSTEM_THREADS, OpenStreetMapTileProviderConstants.TILE_FILESYSTEM_MAXIMUM_QUEUE_SIZE);
mTileSource = pTileSource;
}
#Override
public boolean getUsesDataConnection() {
return false;
}
#Override
protected String getName() {
return "Assets Folder Provider";
}
#Override
protected String getThreadGroupName() {
return "assetsfolder";
}
#Override
protected Runnable getTileLoader() {
return new TileLoader();
}
#Override
public int getMinimumZoomLevel() {
return mTileSource != null ? mTileSource.getMinimumZoomLevel() : MAXIMUM_ZOOMLEVEL;
}
#Override
public int getMaximumZoomLevel() {
return mTileSource != null ? mTileSource.getMaximumZoomLevel() : MINIMUM_ZOOMLEVEL;
}
#Override
public void setTileSource(final ITileSource pTileSource) {
mTileSource = pTileSource;
}
private class TileLoader extends MapTileModuleProviderBase.TileLoader {
#Override
public Drawable loadTile(final MapTileRequestState pState) throws CantContinueException {
if (mTileSource == null) {
return null;
}
final MapTile pTile = pState.getMapTile();
String path = mTileSource.getTileRelativeFilenameString(pTile);
Drawable drawable;
try {
drawable = mTileSource.getDrawable(path);
} catch (final LowMemoryException e) {
// low memory so empty the queue
throw new CantContinueException(e);
}
return drawable;
}
}
}
And
import java.io.File;
import java.io.InputStream;
import java.util.Random;
import org.osmdroid.ResourceProxy;
import org.osmdroid.ResourceProxy.string;
import org.osmdroid.tileprovider.ExpirableBitmapDrawable;
import org.osmdroid.tileprovider.MapTile;
import org.osmdroid.tileprovider.constants.OpenStreetMapTileProviderConstants;
import org.osmdroid.tileprovider.tilesource.ITileSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
public abstract class CustomBitmapTileSourceBase implements ITileSource,
OpenStreetMapTileProviderConstants {
private static final Logger logger = LoggerFactory.getLogger(CustomBitmapTileSourceBase.class);
private static int globalOrdinal = 0;
private final int mMinimumZoomLevel;
private final int mMaximumZoomLevel;
private final int mOrdinal;
protected final String mName;
protected final String mImageFilenameEnding;
protected final Random random = new Random();
private final int mTileSizePixels;
private final string mResourceId;
public CustomBitmapTileSourceBase(final String aName, final string aResourceId,
final int aZoomMinLevel, final int aZoomMaxLevel, final int aTileSizePixels,
final String aImageFilenameEnding) {
mResourceId = aResourceId;
mOrdinal = globalOrdinal++;
mName = aName;
mMinimumZoomLevel = aZoomMinLevel;
mMaximumZoomLevel = aZoomMaxLevel;
mTileSizePixels = aTileSizePixels;
mImageFilenameEnding = aImageFilenameEnding;
}
#Override
public int ordinal() {
return mOrdinal;
}
#Override
public String name() {
return mName;
}
public String pathBase() {
return mName;
}
public String imageFilenameEnding() {
return mImageFilenameEnding;
}
#Override
public int getMinimumZoomLevel() {
return mMinimumZoomLevel;
}
#Override
public int getMaximumZoomLevel() {
return mMaximumZoomLevel;
}
#Override
public int getTileSizePixels() {
return mTileSizePixels;
}
#Override
public String localizedName(final ResourceProxy proxy) {
return proxy.getString(mResourceId);
}
#Override
public Drawable getDrawable(final String aFilePath) {
try {
// default implementation will load the file as a bitmap and create
// a BitmapDrawable from it
final Bitmap bitmap = BitmapFactory.decodeFile(aFilePath);
if (bitmap != null) {
return new ExpirableBitmapDrawable(bitmap);
} else {
// if we couldn't load it then it's invalid - delete it
try {
new File(aFilePath).delete();
} catch (final Throwable e) {
logger.error("Error deleting invalid file: " + aFilePath, e);
}
}
} catch (final OutOfMemoryError e) {
logger.error("OutOfMemoryError loading bitmap: " + aFilePath);
System.gc();
}
return null;
}
#Override
public String getTileRelativeFilenameString(final MapTile tile) {
final StringBuilder sb = new StringBuilder();
sb.append(pathBase());
sb.append('/');
sb.append(tile.getX());
sb.append('_');
sb.append(tile.getY());
sb.append('_');
sb.append(tile.getZoomLevel());
sb.append(imageFilenameEnding());
return sb.toString();
}
#Override
public Drawable getDrawable(final InputStream aFileInputStream) {
try {
// default implementation will load the file as a bitmap and create
// a BitmapDrawable from it
final Bitmap bitmap = BitmapFactory.decodeStream(aFileInputStream);
if (bitmap != null) {
return new ExpirableBitmapDrawable(bitmap);
}
System.gc();
} catch (final OutOfMemoryError e) {
logger.error("OutOfMemoryError loading bitmap");
System.gc();
//throw new LowMemoryException(e);
}
return null;
}
public final class LowMemoryException extends Exception {
private static final long serialVersionUID = 146526524087765134L;
public LowMemoryException(final String pDetailMessage) {
super(pDetailMessage);
}
public LowMemoryException(final Throwable pThrowable) {
super(pThrowable);
}
}
}
Modify method getTileRelativeFilenameString() to get yout tiles (i use the next format: x_y_zoom.png)
Example:
mapView = new MapView(getApplicationContext(), 256);
mapView.setClickable(true);
mapView.setTag("Mapa");
mapView.setTileSource(TileSourceFactory.MAPNIK);
mapView.setMultiTouchControls(true);
mapView.setUseDataConnection(true);
MapTileModuleProviderBase moduleProvider =
new MapTileFileAssetsProvider(ASSETS_TILE_SOURCE);
SimpleRegisterReceiver simpleReceiver =
new SimpleRegisterReceiver(getApplicationContext());
MapTileProviderArray tileProviderArray =
new MapTileProviderArray(ASSETS_TILE_SOURCE, simpleReceiver,
new MapTileModuleProviderBase[] { moduleProvider });
TilesOverlay tilesOverlay =
new TilesOverlay(tileProviderArray, getApplicationContext());
mapView.getOverlays().add(tilesOverlay);
Instead to read directly from assets I copy/deploy the maptiles zipped (following osmdroid map tiles directory structure format) into osmdroid maptiles directory and then declare 3 tile providers, archive, cache and online provider.
public class MapTileProviderAssets extends MapTileProviderArray
implements IMapTileProviderCallback {
private static final String LOG_TAG = "MapTileProviderAssets";
private static final String ASSETS_MAP_DIRECTORY = "map";
private static final String SDCARD_PATH = Environment.getExternalStorageDirectory().getPath();
private static final String OSMDROID_MAP_FILE_SOURCE_DIRECTORY = "osmdroid";
private static final String OSMDROID_MAP_FILE_SOURCE_DIRECTORY_PATH =
SDCARD_PATH + "/" + OSMDROID_MAP_FILE_SOURCE_DIRECTORY;
public MapTileProviderAssets(final Context pContext) {
this(pContext, TileSourceFactory.DEFAULT_TILE_SOURCE);
}
public MapTileProviderAssets(final Context pContext, final ITileSource pTileSource) {
this(pContext, new SimpleRegisterReceiver(pContext),
new NetworkAvailabliltyCheck(pContext), pTileSource);
}
public MapTileProviderAssets(final Context pContext, final IRegisterReceiver pRegisterReceiver,
final INetworkAvailablityCheck aNetworkAvailablityCheck,
final ITileSource pTileSource) {
super(pTileSource, pRegisterReceiver);
final TileWriter tileWriter = new TileWriter();
// copy assets delivered in apk into osmdroid map source dir
// load zip archive first, then cache, then online
final List<String> zipArchivesRelativePathInAssets =
listArchives(pContext.getAssets(), ASSETS_MAP_DIRECTORY);
for (final String zipFileRelativePathInAssets : zipArchivesRelativePathInAssets) {
final String copiedFilePath = copyAssetFile(
pContext.getAssets(), zipFileRelativePathInAssets,
OSMDROID_MAP_FILE_SOURCE_DIRECTORY);
Log.d(LOG_TAG, String.format(
"Archive zip file copied into map source directory %s", copiedFilePath));
}
// list zip files in map archive directory
final Set<String> setZipFileArchivesPath = new HashSet<String>();
FileTools.listFiles(setZipFileArchivesPath, new File(
OSMDROID_MAP_FILE_SOURCE_DIRECTORY_PATH), ".zip", true);
final Set<IArchiveFile> setZipFileArchives = new HashSet<IArchiveFile>();
for (final String zipFileArchivesPath : setZipFileArchivesPath) {
final File zipfile = new File(zipFileArchivesPath);
final IArchiveFile archiveFile = ArchiveFileFactory.getArchiveFile(zipfile);
if (archiveFile != null) {
setZipFileArchives.add(archiveFile);
}
setZipFileArchives.add(archiveFile);
Log.d(LOG_TAG, String.format(
"Archive zip file %s added to map source ", zipFileArchivesPath));
}
final MapTileFileArchiveProvider archiveProvider;
Log.d(LOG_TAG, String.format(
"%s archive zip files will be used as source", setZipFileArchives.size()));
if (setZipFileArchives.size() > 0) {
final IArchiveFile[] pArchives =
setZipFileArchives.toArray(new IArchiveFile[setZipFileArchives.size()]);
archiveProvider = new MapTileFileArchiveProvider(
pRegisterReceiver, pTileSource, pArchives);
} else {
archiveProvider = new MapTileFileArchiveProvider(
pRegisterReceiver, pTileSource);
}
mTileProviderList.add(archiveProvider);
// cache
final MapTileFilesystemProvider fileSystemProvider =
new MapTileFilesystemProvider(pRegisterReceiver, pTileSource);
mTileProviderList.add(fileSystemProvider);
// online tiles
final MapTileDownloader downloaderProvider =
new MapTileDownloader(pTileSource, tileWriter, aNetworkAvailablityCheck);
mTileProviderList.add(downloaderProvider);
}
public static List<String> listArchives(final AssetManager assetManager,
final String subDirectory) {
final List<String> listArchives = new ArrayList<String>();
try {
final String[] lstFiles = assetManager.list(subDirectory);
if (lstFiles != null && lstFiles.length > 0) {
for (final String file : lstFiles) {
if (isZip(file)) {
listArchives.add(subDirectory + "/" + file);
}
// filter files (xxxxx.xxx format) and parse only directories,
// with out this all files are parsed and
// the process is VERY slow
// WARNNING: we could have directories with dot for versioning
else if (isDirectory(file)) {// (file.lastIndexOf(".") != (file.length() - 4)) {
listArchives(assetManager, subDirectory + "/" + file);
}
}
}
} catch (final IOException e) {
Log.w(LOG_TAG, String.format("List error: can't list %s, exception %s",
subDirectory, Log.getStackTraceString(e)));
} catch (final Exception e) {
Log.w(LOG_TAG, String.format("List error: can't list %s, exception %s",
subDirectory, Log.getStackTraceString(e)));
}
return listArchives;
}
private static boolean isZip(final String file) {
return file.endsWith(".zip");
}
private static boolean isDirectory(final String file) {
return file.lastIndexOf(".") != (file.length() - 4);
}
private static String copyAssetFile(final AssetManager assetManager,
final String assetRelativePath,
final String destinationDirectoryOnSdcard) {
InputStream in = null;
OutputStream out = null;
final String newfilePath = SDCARD_PATH + "/" +
destinationDirectoryOnSdcard + "/" + assetRelativePath;
final File newFile = new File(newfilePath);
// copy file only if it doesn't exist yet
if (!newFile.exists()) {
Log.d(LOG_TAG, String.format(
"Copy %s map archive in assets into %s", assetRelativePath, newfilePath));
try {
final File directory = newFile.getParentFile();
if (!directory.exists()) {
if (directory.mkdirs()) {
// Log.d(LOG_TAG, "Directory created: " + directory.getAbsolutePath());
}
}
in = assetManager.open(assetRelativePath);
out = new FileOutputStream(newfilePath);
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
} catch (final Exception e) {
Log.e(LOG_TAG, "Exception during copyAssetFile: " + Log.getStackTraceString(e));
}
}
return newfilePath;
}
private static void copyFile(final InputStream in, final OutputStream out) throws IOException {
final byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
}
}
I need to upload a bitmap to Amazon S3. I have never used S3, and the docs are proving less than helpful as I can't see anything to cover this specific requirement. Unfortunately I'm struggling to find time on this project to spend a whole day learning how it all hangs together so hoping one of you kind people can give me some pointers.
Can you point to me to a source of reference that explains how to push a file to S3, and get a URL reference in return?
More specifically:
- Where do the credentials go when using the S3 Android SDK?
- Do I need to create a bucket before uploading a file, or can they exist outside buckets?
- Which SDK method do I use to push a bitmap up to S3?
- Am I right in thinking I need the CORE and S3 libs to do what I need, and no others?
String ACCESS_KEY="****************",
SECRET_KEY="****************",
MY_BUCKET="bucket_name",
OBJECT_KEY="unique_id";
AWSCredentials credentials = new BasicAWSCredentials(ACCESS_KEY, SECRET_KEY);
AmazonS3 s3 = new AmazonS3Client(credentials);
java.security.Security.setProperty("networkaddress.cache.ttl" , "60");
s3.setRegion(Region.getRegion(Regions.AP_SOUTHEAST_1));
s3.setEndpoint("https://s3-ap-southeast-1.amazonaws.com/");
List<Bucket> buckets=s3.listBuckets();
for(Bucket bucket:buckets){
Log.e("Bucket ","Name "+bucket.getName()+" Owner "+bucket.getOwner()+ " Date " + bucket.getCreationDate());
}
Log.e("Size ", "" + s3.listBuckets().size());
TransferUtility transferUtility = new TransferUtility(s3, getApplicationContext());
UPLOADING_IMAGE=new File(Environment.getExternalStorageDirectory().getPath()+"/Screenshot.png");
TransferObserver observer = transferUtility.upload(MY_BUCKET,OBJECT_KEY,UPLOADING_IMAGE);
observer.setTransferListener(new TransferListener() {
#Override
public void onStateChanged(int id, TransferState state) {
// do something
progress.hide();
path.setText("ID "+id+"\nState "+state.name()+"\nImage ID "+OBJECT_KEY);
}
#Override
public void onProgressChanged(int id, long bytesCurrent, long bytesTotal) {
int percentage = (int) (bytesCurrent / bytesTotal * 100);
progress.setProgress(percentage);
//Display percentage transfered to user
}
#Override
public void onError(int id, Exception ex) {
// do something
Log.e("Error ",""+ex );
}
});
Take a look at the Amazon S3 API documentation to get a feel for what can and can't be done with Amazon S3. Note that there are two APIs, a simpler REST API and a more-involved SOAP API.
You can write your own code to make HTTP requests to interact with the REST API, or use a SOAP library to consume the SOAP API. All of the Amazon services have these standard API endpoints (REST, SOAP) and in theory you can write a client in any programming language!
Fortunately for Android developers, Amazon have released a (Beta) SDK that does all of this work for you. There's a Getting Started guide and Javadocs too. With this SDK you should be able to integrate S3 with your application in a matter of hours.
The Getting Started guide comes with a full sample and shows how to supply the required credentials.
Conceptually, Amazon S3 stores data in Buckets where a bucket contains Objects. Generally you'll use one bucket per application, and add as many objects as you like. S3 doesn't support or have any concept of folders, but you can put slashes (/) in your object names.
We can directly use "Amazone s3" bucket for storing any type of file on server, and we did not need to send any of file to Api server it will reduce the request time.
Gradle File :-
compile 'com.amazonaws:aws-android-sdk-core:2.2.+'
compile 'com.amazonaws:aws-android-sdk-s3:2.2.+'
compile 'com.amazonaws:aws-android-sdk-ddb:2.2.+'
Manifest File :-
<service android:name="com.amazonaws.mobileconnectors.s3.transferutility.TransferService"
android:enabled="true" />
FileUploader Function in any Class :-
private void setUPAmazon() {
//we Need Identity Pool ID like :- "us-east-1:f224****************8"
CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(getActivity(),
"us-east-1:f224****************8", Regions.US_EAST_1);
AmazonS3 s3 = new AmazonS3Client(credentialsProvider);
final TransferUtility transferUtility = new TransferUtility(s3, getActivity());
final File file = new File(mCameraUri.getPath());
final TransferObserver observer = transferUtility.upload(GeneralValues.AMAZON_BUCKET, file.getName(), file, CannedAccessControlList.PublicRead);
observer.setTransferListener(new TransferListener() {
#Override
public void onStateChanged(int id, TransferState state) {
Log.e("onStateChanged", id + state.name());
if (state == TransferState.COMPLETED) {
String url = "https://"+GeneralValues.AMAZON_BUCKET+".s3.amazonaws.com/" + observer.getKey();
Log.e("URL :,", url);
//we just need to share this File url with Api service request.
}
}
#Override
public void onProgressChanged(int id, long bytesCurrent, long bytesTotal) {
}
#Override
public void onError(int id, Exception ex) {
Toast.makeText(getActivity(), "Unable to Upload", Toast.LENGTH_SHORT).show();
ex.printStackTrace();
}
});
}
you can use the below mentioned class to Upload data to amazon s3 buckets.
public class UploadAmazonS3{
private CognitoCachingCredentialsProvider credentialsProvider = null;
private AmazonS3Client s3Client = null;
private TransferUtility transferUtility = null;
private static UploadAmazonS3 uploadAmazonS3;
/**
* Creating single tone object by defining private.
* <P>
* At the time of creating
* </P>*/
private UploadAmazonS3(Context context, String canito_pool_id)
{
/**
* Creating the object of the getCredentialProvider object. */
credentialsProvider=getCredentialProvider(context,canito_pool_id);
/**
* Creating the object of the s3Client */
s3Client=getS3Client(context,credentialsProvider);
/**
* Creating the object of the TransferUtility of the Amazone.*/
transferUtility=getTransferUtility(context,s3Client);
}
public static UploadAmazonS3 getInstance(Context context, String canito_pool_id)
{
if(uploadAmazonS3 ==null)
{
uploadAmazonS3 =new UploadAmazonS3(context,canito_pool_id);
return uploadAmazonS3;
}else
{
return uploadAmazonS3;
}
}
/**
* <h3>Upload_data</h3>
* <P>
* Method is use to upload data in the amazone server.
*
* </P>*/
public void uploadData(final String bukkate_name, final File file, final Upload_CallBack callBack)
{
Utility.printLog("in amazon upload class uploadData "+file.getName());
if(transferUtility!=null&&file!=null)
{
TransferObserver observer=transferUtility.upload(bukkate_name,file.getName(),file);
observer.setTransferListener(new TransferListener()
{
#Override
public void onStateChanged(int id, TransferState state)
{
if(state.equals(TransferState.COMPLETED))
{
callBack.sucess(com.tarha_taxi.R.string.AMAZON_END_POINT_LINK+bukkate_name+"/"+file.getName());
}
}
#Override
public void onProgressChanged(int id, long bytesCurrent, long bytesTotal)
{
}
#Override
public void onError(int id, Exception ex)
{
callBack.error(id+":"+ex.toString());
}
});
}else
{
callBack.error("Amamzones3 is not intialize or File is empty !");
}
}
/**
* This method is used to get the CredentialProvider and we provide only context as a parameter.
* #param context Here, we are getting the context from calling Activity.*/
private CognitoCachingCredentialsProvider getCredentialProvider(Context context,String pool_id)
{
if (credentialsProvider == null)
{
credentialsProvider = new CognitoCachingCredentialsProvider(
context.getApplicationContext(),
pool_id, // Identity Pool ID
AMAZON_REGION // Region
);
}
return credentialsProvider;
}
/**
* This method is used to get the AmazonS3 Client
* and we provide only context as a parameter.
* and from here we are calling getCredentialProvider() function.
* #param context Here, we are getting the context from calling Activity.*/
private AmazonS3Client getS3Client(Context context,CognitoCachingCredentialsProvider cognitoCachingCredentialsProvider)
{
if (s3Client == null)
{
s3Client = new AmazonS3Client(cognitoCachingCredentialsProvider);
s3Client.setRegion(Region.getRegion(AMAZON_REGION));
s3Client.setEndpoint(context.getString(com.tarha_taxi.R.string.AMAZON_END_POINT_LINK));
}
return s3Client;
}
/**
* This method is used to get the Transfer Utility
* and we provide only context as a parameter.
* and from here we are, calling getS3Client() function.
* #param context Here, we are getting the context from calling Activity.*/
private TransferUtility getTransferUtility(Context context,AmazonS3Client amazonS3Client)
{
if (transferUtility == null)
{
transferUtility = new TransferUtility(amazonS3Client,context.getApplicationContext());
}
return transferUtility;
}
/**
* Interface for the sucess callback fro the Amazon uploading .
* */
public interface Upload_CallBack
{
/**
*Method for sucess .
* #param sucess it is true on sucess and false for falure.*/
void sucess(String sucess);
/**
* Method for falure.
* #param errormsg contains the error message.*/
void error(String errormsg);
}
}
use the below method to access the above calss :
private void uploadToAmazon() {
dialogL.show();
UploadAmazonS3 amazonS3 = UploadAmazonS3.getInstance(getActivity(), getString(R.string.AMAZON_POOL_ID));
amazonS3.uploadData(getString(R.string.BUCKET_NAME), Utility.renameFile(VariableConstants.TEMP_PHOTO_FILE_NAME, phone.getText().toString().substring(1) + ".jpg"), new UploadAmazonS3.Upload_CallBack() {
#Override
public void sucess(String sucess) {
if (Utility.isNetworkAvailable(getActivity())) {
dialogL.dismiss();
/**
* to set the image into image view and
* add the write the image in the file
*/
activity.user_image.setTag(setTarget(progress_bar));
Picasso.with(getActivity()).load(getString(R.string.AMAZON_IMAGE_LINK) + phone.getText().toString().substring(1) + ".jpg").
networkPolicy(NetworkPolicy.NO_CACHE).memoryPolicy(MemoryPolicy.NO_CACHE).into((Target) activity.user_image.getTag());
Utility.printLog("amazon upload success ");
new BackgroundForUpdateProfile().execute();
} else {
dialogL.dismiss();
Utility.showToast(getActivity(), getResources().getString(R.string.network_connection_fail));
}
}
#Override
public void error(String errormsg) {
dialogL.dismiss();
Utility.showToast(getActivity(), getResources().getString(R.string.network_connection_fail));
}
});
}
You can use a library called S3UploadService. First you would need to convert your Bitmap to a File. To do so take a look at this post:
Convert Bitmap to File
S3UploadService is a library that handles uploads to Amazon S3. It provides a service called S3UploadService with a static method where you provide a Context (so the static method can start the service), a File, a boolean indicating if said file should be deleted after upload completion and optionally you can set a callback (Not like an ordinary callback though. The way this works is explained in the README file).
It's an IntentService so the upload will run even if the user kills the app while uploading (because its lifecycle is not attached to the app's lifecycle).
To use this library you just have to declare the service in your manifest:
<application
...>
...
<service
android:name="com.onecode.s3.service.S3UploadService"
android:exported="false" />
</application>
Then you build an S3BucketData instance and make a call to S3UploadService.upload():
S3Credentials s3Credentials = new S3Credentials(accessKey, secretKey, sessionToken);
S3BucketData s3BucketData = new S3BucketData.Builder()
.setCredentials(s3Credentials)
.setBucket(bucket)
.setKey(key)
.setRegion(region)
.build();
S3UploadService.upload(getActivity(), s3BucketData, file, null);
To add this library you need to add the JitPack repo to your root build.gradle:
allprojects {
repositories {
...
maven { url "https://jitpack.io" }
}
}
and then add the dependency:
dependencies {
compile 'com.github.OneCodeLabs:S3UploadService:1.0.0#aar'
}
Here is a link to the repo:
https://github.com/OneCodeLabs/S3UploadService
This answer is a bit late, but I hope it helps someone
you can upload image and download image in s3 amazon. you make a simple class use this WebserviceAmazon
public class WebserviceAmazon extends AsyncTask<Void, Void, Void> {
private String mParams;
private String mResult = "x";
WebServiceInterface<String, String> mInterface;
private int mRequestType;
private String UserId;
private Context mContext;
public WebserviceAmazon(Context context,String imagePath,String AppId,int type) {
this.mContext = context;
this.mParams = imagePath;
this.mRequestType = type;
this.UserId = AppId;
}
public void result(WebServiceInterface<String, String> myInterface) {
this.mInterface = myInterface;
}
#Override
protected Void doInBackground(Void... params) {
String ACCESS_KEY ="abc..";
String SECRET_KEY = "klm...";
try {
if (mRequestType == 1) { // POST
AmazonS3Client s3Client = new AmazonS3Client(new BasicAWSCredentials(ACCESS_KEY, SECRET_KEY));
PutObjectRequest request = new PutObjectRequest("bucketName", "imageName", new File(mParams));
s3Client.putObject(request);
mResult = "success";
} if (mRequestType == 2) { // For get image data
AmazonS3Client s3Client = new AmazonS3Client(new BasicAWSCredentials(ACCESS_KEY, SECRET_KEY));
S3Object object = s3Client.getObject(new GetObjectRequest("bucketName", mParams));
S3ObjectInputStream objectContent = object.getObjectContent();
byte[] byteArray = IOUtils.toByteArray(objectContent);
Bitmap bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
mResult = "success";
}
} catch (Exception e) {
mResult = e.toString();
e.printStackTrace();
}
return null;
}
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
}
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
mInterface.success(this.mResult);
}
public interface WebServiceInterface<E, R> {
public void success(E reslut);
public void error(R Error);
}
}
call this webservice any where in project
WebserviceAmazon amazon = new WebserviceAmazon(getActivity(), imageName, "", 2);
amazon.result(new WebserviceAmazon.WebServiceInterface<String, String>() {
#Override
public void success(String reslut) {
}
#Override
public void error(String Error) {
}
});
return totalPoints;
}
here is my code to upload image to Amazon AWS S3 bucket
Hope this is helpful for you
First let me clear some key points
you can either take image from camera or pick image from gallery ,AWS store images as a file so first thing you need to store image to local dir and get path of image then create a file from that path after this you will be able to upload that imagefile to AWS.
first you need to add configration on Oncreate
BasicAWSCredentials credentials = new BasicAWSCredentials(KEY,SECRET);
s3 = new AmazonS3Client(credentials);
s3.setRegion(Region.getRegion(Regions.US_EAST_1));
private void uploadFile() {
verifyStoragePermissions(CustomCameraActivity.this);
TransferUtility transferUtility =
TransferUtility.builder()
.context(getApplicationContext())
.awsConfiguration(AWSMobileClient.getInstance().getConfiguration())
.s3Client(s3)
.build();
TransferObserver uploadObserver= null;
File file2 = FileUtils.getFile(CustomCameraActivity.this, storageImagePath);//here i am converting path to file ,,FileUtils.getFile is custom class
uploadObserver = transferUtility.upload("your bucket name", imageNameWithoutExtension + ".jpg", file2);// imagenamewithoutExtension is actually the name that you want to store
uploadObserver.setTransferListener(new TransferListener() {
#Override
public void onStateChanged(int id, TransferState state) {
if (TransferState.COMPLETED == state) {
Toast.makeText(getApplicationContext(), "Upload Completed!", Toast.LENGTH_SHORT).show();
uploadResourcesApi(uploadResoucesURL);
//imageFile.delete();
//file2.delete();
} else if (TransferState.FAILED == state) {
//imageFile.delete();
//file2.delete();
}
}
#Override
public void onProgressChanged(int id, long bytesCurrent, long bytesTotal) {
float percentDonef = ((float) bytesCurrent / (float) bytesTotal) * 100;
int percentDone = (int) percentDonef;
//tvFileName.setText("ID:" + id + "|bytesCurrent: " + bytesCurrent + "|bytesTotal: " + bytesTotal + "|" + percentDone + "%");
}
#Override
public void onError(int id, Exception ex) {
ex.printStackTrace();
}
});
}
this is fileUtils class
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.util.Log;
import android.webkit.MimeTypeMap;
import java.io.File;
import java.io.FileFilter;
import java.text.DecimalFormat;
import java.util.Comparator;
/**
* #version 2009-07-03
* #author Peli
* #version 2013-12-11
* #author paulburke (ipaulpro)
*/
public class FileUtils {
private FileUtils() {} //private constructor to enforce Singleton pattern
/** TAG for log messages. */
static final String TAG = "FileUtils";
private static final boolean DEBUG = false; // Set to true to enable logging
public static final String MIME_TYPE_AUDIO = "audio/*";
public static final String MIME_TYPE_TEXT = "text/*";
public static final String MIME_TYPE_IMAGE = "image/*";
public static final String MIME_TYPE_VIDEO = "video/*";
public static final String MIME_TYPE_APP = "application/*";
public static final String HIDDEN_PREFIX = ".";
/**
* Gets the extension of a file name, like ".png" or ".jpg".
*
* #param uri
* #return Extension including the dot("."); "" if there is no extension;
* null if uri was null.
*/
public static String getExtension(String uri) {
if (uri == null) {
return null;
}
int dot = uri.lastIndexOf(".");
if (dot >= 0) {
return uri.substring(dot);
} else {
// No extension.
return "";
}
}
/**
* #return Whether the URI is a local one.
*/
public static boolean isLocal(String url) {
if (url != null && !url.startsWith("http://") && !url.startsWith("https://")) {
return true;
}
return false;
}
/**
* #return True if Uri is a MediaStore Uri.
* #author paulburke
*/
public static boolean isMediaUri(Uri uri) {
return "media".equalsIgnoreCase(uri.getAuthority());
}
/**
* Convert File into Uri.
*
* #param file
* #return uri
*/
public static Uri getUri(File file) {
if (file != null) {
return Uri.fromFile(file);
}
return null;
}
/**
* Returns the path only (without file name).
*
* #param file
* #return
*/
public static File getPathWithoutFilename(File file) {
if (file != null) {
if (file.isDirectory()) {
// no file to be split off. Return everything
return file;
} else {
String filename = file.getName();
String filepath = file.getAbsolutePath();
// Construct path without file name.
String pathwithoutname = filepath.substring(0,
filepath.length() - filename.length());
if (pathwithoutname.endsWith("/")) {
pathwithoutname = pathwithoutname.substring(0, pathwithoutname.length() - 1);
}
return new File(pathwithoutname);
}
}
return null;
}
/**
* #return The MIME type for the given file.
*/
public static String getMimeType(File file) {
String extension = getExtension(file.getName());
if (extension.length() > 0)
return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.substring(1));
return "application/octet-stream";
}
/**
* #return The MIME type for the give Uri.
*/
public static String getMimeType(Context context, Uri uri) {
File file = new File(getPath(context, uri));
return getMimeType(file);
}
/**
* #param uri The Uri to check.
* #return Whether the Uri authority is {#link LocalStorageProvider}.
* #author paulburke
*/
public static boolean isLocalStorageDocument(Uri uri) {
return LocalStorageProvider.AUTHORITY.equals(uri.getAuthority());
}
/**
* #param uri The Uri to check.
* #return Whether the Uri authority is ExternalStorageProvider.
* #author paulburke
*/
public static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
/**
* #param uri The Uri to check.
* #return Whether the Uri authority is DownloadsProvider.
* #author paulburke
*/
public static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
/**
* #param uri The Uri to check.
* #return Whether the Uri authority is MediaProvider.
* #author paulburke
*/
public static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
/**
* #param uri The Uri to check.
* #return Whether the Uri authority is Google Photos.
*/
public static boolean isGooglePhotosUri(Uri uri) {
return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}
/**
* Get the value of the data column for this Uri. This is useful for
* MediaStore Uris, and other file-based ContentProviders.
*
* #param context The context.
* #param uri The Uri to query.
* #param selection (Optional) Filter used in the query.
* #param selectionArgs (Optional) Selection arguments used in the query.
* #return The value of the _data column, which is typically a file path.
* #author paulburke
*/
public static String getDataColumn(Context context, Uri uri, String selection,
String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = {
column
};
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
null);
if (cursor != null && cursor.moveToFirst()) {
if (DEBUG)
DatabaseUtils.dumpCursor(cursor);
final int column_index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(column_index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
public static String getPath(final Context context, final Uri uri) {
if (DEBUG)
Log.d(TAG + " File -",
"Authority: " + uri.getAuthority() +
", Fragment: " + uri.getFragment() +
", Port: " + uri.getPort() +
", Query: " + uri.getQuery() +
", Scheme: " + uri.getScheme() +
", Host: " + uri.getHost() +
", Segments: " + uri.getPathSegments().toString()
);
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
// LocalStorageProvider
if (isLocalStorageDocument(uri)) {
// The path is the id
return DocumentsContract.getDocumentId(uri);
}
// ExternalStorageProvider
else if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
// TODO handle non-primary volumes
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[] {
split[1]
};
return getDataColumn(context, contentUri, selection, selectionArgs);
}
}
// MediaStore (and general)
else if ("content".equalsIgnoreCase(uri.getScheme())) {
// Return the remote address
if (isGooglePhotosUri(uri))
return uri.getLastPathSegment();
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
public static File getFile(Context context, Uri uri) {
if (uri != null) {
String path = getPath(context, uri);
if (path != null && isLocal(path)) {
return new File(path);
}
}
return null;
}
public static String getReadableFileSize(int size) {
final int BYTES_IN_KILOBYTES = 1024;
final DecimalFormat dec = new DecimalFormat("###.#");
final String KILOBYTES = " KB";
final String MEGABYTES = " MB";
final String GIGABYTES = " GB";
float fileSize = 0;
String suffix = KILOBYTES;
if (size > BYTES_IN_KILOBYTES) {
fileSize = size / BYTES_IN_KILOBYTES;
if (fileSize > BYTES_IN_KILOBYTES) {
fileSize = fileSize / BYTES_IN_KILOBYTES;
if (fileSize > BYTES_IN_KILOBYTES) {
fileSize = fileSize / BYTES_IN_KILOBYTES;
suffix = GIGABYTES;
} else {
suffix = MEGABYTES;
}
}
}
return String.valueOf(dec.format(fileSize) + suffix);
}
public static Bitmap getThumbnail(Context context, File file) {
return getThumbnail(context, getUri(file), getMimeType(file));
}
public static Bitmap getThumbnail(Context context, Uri uri) {
return getThumbnail(context, uri, getMimeType(context, uri));
}
public static Bitmap getThumbnail(Context context, Uri uri, String mimeType) {
if (DEBUG)
Log.d(TAG, "Attempting to get thumbnail");
if (!isMediaUri(uri)) {
Log.e(TAG, "You can only retrieve thumbnails for images and videos.");
return null;
}
Bitmap bm = null;
if (uri != null) {
final ContentResolver resolver = context.getContentResolver();
Cursor cursor = null;
try {
cursor = resolver.query(uri, null, null, null, null);
if (cursor.moveToFirst()) {
final int id = cursor.getInt(0);
if (DEBUG)
Log.d(TAG, "Got thumb ID: " + id);
if (mimeType.contains("video")) {
bm = MediaStore.Video.Thumbnails.getThumbnail(
resolver,
id,
MediaStore.Video.Thumbnails.MINI_KIND,
null);
}
else if (mimeType.contains(FileUtils.MIME_TYPE_IMAGE)) {
bm = MediaStore.Images.Thumbnails.getThumbnail(
resolver,
id,
MediaStore.Images.Thumbnails.MINI_KIND,
null);
}
}
} catch (Exception e) {
if (DEBUG)
Log.e(TAG, "getThumbnail", e);
} finally {
if (cursor != null)
cursor.close();
}
}
return bm;
}
public static Comparator<File> sComparator = new Comparator<File>() {
#Override
public int compare(File f1, File f2) {
// Sort alphabetically by lower case, which is much cleaner
return f1.getName().toLowerCase().compareTo(
f2.getName().toLowerCase());
}
};
public static FileFilter sFileFilter = new FileFilter() {
#Override
public boolean accept(File file) {
final String fileName = file.getName();
// Return files only (not directories) and skip hidden files
return file.isFile() && !fileName.startsWith(HIDDEN_PREFIX);
}
};
public static FileFilter sDirFilter = new FileFilter() {
#Override
public boolean accept(File file) {
final String fileName = file.getName();
// Return directories only and skip hidden directories
return file.isDirectory() && !fileName.startsWith(HIDDEN_PREFIX);
}
};
public static Intent createGetContentIntent() {
// Implicitly allow the user to select a particular kind of data
final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
// The MIME data type filter
intent.setType("*/*");
// Only return URIs that can be opened with ContentResolver
intent.addCategory(Intent.CATEGORY_OPENABLE);
return intent;
}
}
then you will also need this class
public class LocalStorageProvider extends DocumentsProvider {
public static final String AUTHORITY = "com.ianhanniballake.localstorage.documents";
private final static String[] DEFAULT_ROOT_PROJECTION = new String[] {
Root.COLUMN_ROOT_ID,
Root.COLUMN_FLAGS, Root.COLUMN_TITLE, Root.COLUMN_DOCUMENT_ID, Root.COLUMN_ICON,
Root.COLUMN_AVAILABLE_BYTES
};
private final static String[] DEFAULT_DOCUMENT_PROJECTION = new String[] {
Document.COLUMN_DOCUMENT_ID,
Document.COLUMN_DISPLAY_NAME, Document.COLUMN_FLAGS, Document.COLUMN_MIME_TYPE,
Document.COLUMN_SIZE,
Document.COLUMN_LAST_MODIFIED
};
#Override
public Cursor queryRoots(final String[] projection) throws FileNotFoundException {
final MatrixCursor result = new MatrixCursor(projection != null ? projection
: DEFAULT_ROOT_PROJECTION);
File homeDir = Environment.getExternalStorageDirectory();
final MatrixCursor.RowBuilder row = result.newRow();
// These columns are required
row.add(Root.COLUMN_ROOT_ID, homeDir.getAbsolutePath());
row.add(Root.COLUMN_DOCUMENT_ID, homeDir.getAbsolutePath());
row.add(Root.COLUMN_TITLE, "Internal storage");
row.add(Root.COLUMN_FLAGS, Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_CREATE);
row.add(Root.COLUMN_ICON, R.drawable.ic_launcher_foreground);
// These columns are optional
row.add(Root.COLUMN_AVAILABLE_BYTES, homeDir.getFreeSpace());
// Root.COLUMN_MIME_TYPE is another optional column and useful if you
return result;
}
#Override
public String createDocument(final String parentDocumentId, final String mimeType,
final String displayName) throws FileNotFoundException {
File newFile = new File(parentDocumentId, displayName);
try {
newFile.createNewFile();
return newFile.getAbsolutePath();
} catch (IOException e) {
Log.e(LocalStorageProvider.class.getSimpleName(), "Error creating new file " + newFile);
}
return null;
}
#Override
public AssetFileDescriptor openDocumentThumbnail(final String documentId, final Point sizeHint,
final CancellationSignal signal) throws FileNotFoundException {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(documentId, options);
final int targetHeight = 2 * sizeHint.y;
final int targetWidth = 2 * sizeHint.x;
final int height = options.outHeight;
final int width = options.outWidth;
options.inSampleSize = 1;
if (height > targetHeight || width > targetWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
while ((halfHeight / options.inSampleSize) > targetHeight
|| (halfWidth / options.inSampleSize) > targetWidth) {
options.inSampleSize *= 2;
}
}
options.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeFile(documentId, options);
// Write out the thumbnail to a temporary file
File tempFile = null;
FileOutputStream out = null;
try {
tempFile = File.createTempFile("thumbnail", null, getContext().getCacheDir());
out = new FileOutputStream(tempFile);
bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
} catch (IOException e) {
Log.e(LocalStorageProvider.class.getSimpleName(), "Error writing thumbnail", e);
return null;
} finally {
if (out != null)
try {
out.close();
} catch (IOException e) {
Log.e(LocalStorageProvider.class.getSimpleName(), "Error closing thumbnail", e);
}
}
// It appears the Storage Framework UI caches these results quite
// aggressively so there is little reason to
// write your own caching layer beyond what you need to return a single
// AssetFileDescriptor
return new AssetFileDescriptor(ParcelFileDescriptor.open(tempFile,
ParcelFileDescriptor.MODE_READ_ONLY), 0,
AssetFileDescriptor.UNKNOWN_LENGTH);
}
#Override
public Cursor queryChildDocuments(final String parentDocumentId, final String[] projection,
final String sortOrder) throws FileNotFoundException {
// Create a cursor with either the requested fields, or the default
// projection if "projection" is null.
final MatrixCursor result = new MatrixCursor(projection != null ? projection
: DEFAULT_DOCUMENT_PROJECTION);
final File parent = new File(parentDocumentId);
for (File file : parent.listFiles()) {
// Don't show hidden files/folders
if (!file.getName().startsWith(".")) {
// Adds the file's display name, MIME type, size, and so on.
includeFile(result, file);
}
}
return result;
}
#Override
public Cursor queryDocument(final String documentId, final String[] projection)
throws FileNotFoundException {
// Create a cursor with either the requested fields, or the default
// projection if "projection" is null.
final MatrixCursor result = new MatrixCursor(projection != null ? projection
: DEFAULT_DOCUMENT_PROJECTION);
includeFile(result, new File(documentId));
return result;
}
private void includeFile(final MatrixCursor result, final File file)
throws FileNotFoundException {
final MatrixCursor.RowBuilder row = result.newRow();
// These columns are required
row.add(Document.COLUMN_DOCUMENT_ID, file.getAbsolutePath());
row.add(Document.COLUMN_DISPLAY_NAME, file.getName());
String mimeType = getDocumentType(file.getAbsolutePath());
row.add(Document.COLUMN_MIME_TYPE, mimeType);
int flags = file.canWrite() ? Document.FLAG_SUPPORTS_DELETE | Document.FLAG_SUPPORTS_WRITE
: 0;
// We only show thumbnails for image files - expect a call to
// openDocumentThumbnail for each file that has
// this flag set
if (mimeType.startsWith("image/"))
flags |= Document.FLAG_SUPPORTS_THUMBNAIL;
row.add(Document.COLUMN_FLAGS, flags);
// COLUMN_SIZE is required, but can be null
row.add(Document.COLUMN_SIZE, file.length());
// These columns are optional
row.add(Document.COLUMN_LAST_MODIFIED, file.lastModified());
// Document.COLUMN_ICON can be a resource id identifying a custom icon.
// The system provides default icons
// based on mime type
// Document.COLUMN_SUMMARY is optional additional information about the
// file
}
#Override
public String getDocumentType(final String documentId) throws FileNotFoundException {
File file = new File(documentId);
if (file.isDirectory())
return Document.MIME_TYPE_DIR;
// From FileProvider.getType(Uri)
final int lastDot = file.getName().lastIndexOf('.');
if (lastDot >= 0) {
final String extension = file.getName().substring(lastDot + 1);
final String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
if (mime != null) {
return mime;
}
}
return "application/octet-stream";
}
#Override
public void deleteDocument(final String documentId) throws FileNotFoundException {
new File(documentId).delete();
}
#Override
public ParcelFileDescriptor openDocument(final String documentId, final String mode,
final CancellationSignal signal) throws FileNotFoundException {
File file = new File(documentId);
final boolean isWrite = (mode.indexOf('w') != -1);
if (isWrite) {
return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_WRITE);
} else {
return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
}
}
#Override
public boolean onCreate() {
return true;
}
}