i need to save a camera image from sd card to sqlite in android. The problem i am facing is out of memory exception. How i can compress this image and sav it in sqlite. The image format is jpeg
thanks in advance
jibysthomas
I do not know if this is the best way to save storage space using SQLite and I am still looking for it, but here we go.
You can select the source of your image, such as gallery or camera and below is the code.
private void selectProductImage() {
final CharSequence[] itens = {"Use Camera", "Gallery", "Cancel"};
AlertDialog.Builder builder = new AlertDialog.Builder(this,R.style.AlertDialog);
builder.setItems(itens, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (itens[which].equals("Use Camera")) {
Toast.makeText(YourActivity.this, "Use Camera", Toast.LENGTH_SHORT).show();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{Manifest.permission.CAMERA}, MY_CAMERA_PERMISSION_CODE);
} else {
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);
}
} else if (itens[which].equals("Gallery")) {
Toast.makeText(YourActivity.this, "Gallery", Toast.LENGTH_SHORT).show();
Intent galleryIntent = new Intent();
galleryIntent.setAction(Intent.ACTION_GET_CONTENT);
galleryIntent.setType("image/*");
startActivityForResult(galleryIntent, REQUEST_GALLERY_PHOTO);
} else if (itens[which].equals("Cancel")) {
dialog.dismiss();
}
}
});
builder.show();
}
Maybe you need permission to use the camera
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == MY_CAMERA_PERMISSION_CODE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//Toast.makeText(this, "camera permission granted", Toast.LENGTH_LONG).show();
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);
} else {
Toast.makeText(this, "camera permission denied", Toast.LENGTH_LONG).show();
}
return;
}
}
Here is how to handle the image from the source you selected.
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK) {
Bitmap bitmap = Bitmap.createScaledBitmap((Bitmap) data.getExtras().get("data"),96, 96, true);
mProductImage.setImageBitmap(bitmap);
isPriviteImage = true;
}
if (requestCode == REQUEST_GALLERY_PHOTO && resultCode == RESULT_OK && data != null) {
//mProductImage.setImageURI(data.getData());
// INSERT IMAGE INTO SQLite
Uri uri = data.getData();
try {
InputStream inputStream = getContentResolver().openInputStream(uri);
Bitmap bitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeStream(inputStream),96, 96, true);
mProductImage.setImageBitmap(bitmap);
isPriviteImage = true;
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
As you can notice in my example, there is no place to save the image case you selected camera and I placed the image on an ImageView variable named mProductImage.
From now, you can use a Button to save the image in your SQLite Database. Here is the function you can use for it.
private void saveImage() {
productTablePath = Environment.getExternalStorageDirectory()+"/YourAditionalPath/";
ProductDatabaseHelper productDatabaseHelper = new ProductDatabaseHelper(getApplicationContext(), "dbname.db", productTablePath);
productListTable = productDatabaseHelper.getWritableDatabase();
productRepository = new ProductRepository(productListTable);
try {
if (isPriviteImage) {
productRepository.addProduct(imageViewToByte(mProductImage));
isPriviteImage = false;
} else {
productRepository.addProduct(null);
}
mProductImage.setImageResource(R.drawable.shopping_cart_black_48dp);
} catch (Exception e) {
e.printStackTrace();
}
}
Where imageViewToByte functon is:
private byte[] imageViewToByte(CircleImageView image) {
Bitmap bitmap = ((BitmapDrawable)image.getDrawable()).getBitmap();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG,100,stream);
byte[] byteArray = stream.toByteArray();
return byteArray;
}
Now you need to implement the SQLiteOpenHelper. You need to create a new class for this. The java file name I used for this was ProductDatabaseHelper.java.
public class ProductDatabaseHelper extends SQLiteOpenHelper {
private static int dbVersion = 1;
public ProductDatabaseHelper(Context context, String name, String storageDirectory) {
super(context, storageDirectory+name, null, dbVersion);
}
#Override
public void onCreate(SQLiteDatabase db) {
StringBuilder sql = new StringBuilder();
sql.append("CREATE TABLE IF NOT EXISTS PRODUCTLIST (");
sql.append(" IMAGE BLOB,");
db.execSQL(sql.toString());
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
Now you need to implement your CRUD (Create new item, Read, Update and Delete).
public class ProductRepository {
SQLiteDatabase instance;
public ProductRepository(SQLiteDatabase instance) {
this.instance = instance;
}
public void addProduct(byte[] image){
ContentValues contentValues = new ContentValues();
contentValues.put("IMAGE",image);
instance.insertOrThrow("PRODUCTLIST",null, contentValues);
}
}
It is important to mention that the compression of the image was made in the onActivityResult() for both source image (camera and gallery).
with the command:
Bitmap bitmap = Bitmap.createScaledBitmap(capturedImage, width, height, true);
Besides that, here is a link where we can read a little bit about compression.
https://androidwave.com/capture-image-from-camera-gallery/
If you have a better way to compress images to save in SQLite Database, please post your code here!
Related
I am building an app to upload images to my company server
I am using koush-ion for the upload,
now my problem is I have to dynamically change the URL for upload depending on information entered in another activity(LoginActivity) via edittext boxes
and I don't understand how to do that
so what I want to happen is the client enters thier Email, password and clientID(4 digits)(in LoginActivity) and the app uses that to build a url for the upload
like this one(in CameraActivity)
https://www.blahpractice.co.za/files-upload-ruben.asp?MyForm=Yes&ClientID=1234&Username=man#blahpractice.co.za&Pwd=BlahBlah123#
I got this From the koush github, and i am unsure if this is what i am looking for and also how to implement data from another activity in koush-ion
Post application/x-www-form-urlencoded and read a String
Ion.with(getContext())
.load("https://koush.clockworkmod.com/test/echo")
.setBodyParameter("goop", "noop")
.setBodyParameter("foo", "bar")
.asString()
.setCallback(...)
Camera Activity
public class CameraActivity extends AppCompatActivity implements
View.OnClickListener{
private final int PICK_IMAGE = 12345;
private final int REQUEST_CAMERA = 6352;
private static final int REQUEST_CAMERA_ACCESS_PERMISSION =5674;
private Bitmap bitmap;
private ImageView imageView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
imageView =findViewById(R.id.imageView);
Button fromCamera=findViewById(R.id.fromCamera);
Button fromGallery=findViewById(R.id.fromGallery);
Button upload=findViewById(R.id.upload);
upload.setOnClickListener(this);
fromCamera.setOnClickListener(this);
fromGallery.setOnClickListener(this);
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)) {
fromCamera.setVisibility(View.GONE);
}
}
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.fromCamera:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
&& ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.CAMERA},
REQUEST_CAMERA_ACCESS_PERMISSION);
}else {
getImageFromCamera();
}
break;
case R.id.fromGallery:
getImageFromGallery();
break;
case R.id.upload:
if (bitmap != null)
uploadImageToServer();
break;
}
}
private void uploadImageToServer() {
I want to call the url here
File imageFile = persistImage(bitmap, "SP_Upload");
Ion.with(this)
.load("https://www.Blahpractice.co.za/files-upload-ruben.asp?MyForm=Yes")
.setMultipartFile("SP-LOG", "image/jpeg", imageFile)
.asJsonObject()
.setCallback(new FutureCallback<JsonObject>() {
#Override
public void onCompleted(Exception e, JsonObject result) {
}
});
}
private File persistImage(Bitmap bitmap, String name) {
File filesDir = getApplicationContext().getFilesDir();
File imageFile = new File(filesDir, name + ".jpg");
OutputStream os;
try {
os = new FileOutputStream(imageFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
os.flush();
os.close();
} catch (Exception e) {
Log.e(getClass().getSimpleName(), "Error writing bitmap", e);
}
return imageFile;
}
private void getImageFromCamera() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, REQUEST_CAMERA);
}
private void getImageFromGallery() {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE);
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_IMAGE) {
if (resultCode == Activity.RESULT_OK) {
try {
InputStream inputStream = getContentResolver().openInputStream(data.getData());
bitmap = BitmapFactory.decodeStream(inputStream);
imageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
} else if (requestCode == REQUEST_CAMERA) {
if (resultCode == Activity.RESULT_OK) {
Bundle extras = data.getExtras();
bitmap = (Bitmap) extras.get("data");
imageView.setImageBitmap(bitmap);
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == REQUEST_CAMERA_ACCESS_PERMISSION) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
getImageFromCamera();
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
}
LoginActivity
public class LoginActivity extends AppCompatActivity {
private EditText email, password, id;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
email=findViewById(R.id.emailtext);
password=findViewById(R.id.pwdtext);
id=findViewById(R.id.clientid);
Button loginBtn=findViewById(R.id.button);
loginBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String emailAddress=email.getText().toString().trim();
String userPassword=password.getText().toString().trim();
String clientId=id.getText().toString().trim();
Intent intent=new Intent(LoginActivity.this, CameraActivity.class);
intent.putExtra("clientId", clientId);
intent.putExtra("email", emailAddress);
intent.putExtra("password", userPassword);
startActivity(intent);
}
});
}
}
You could store the url on the shared preferences and retrieve it every time you execute your upload task and set it on the .load() method.
Also, what you need to send an image to your server is a multipart post. I haven't used Ion but I have used multipart in other libraries like OkHttp, I´ve copied the method that appears on the Ion documentation:
String dynamicUrl = PreferenceManager.getDefaultSharedPreferences(context).getString(CURRENT_SELECTED_URL, null);
File myImage = new File(myImagePath);
if(dynamicUrl != null) {
Ion.with(getContext())
.load(dynamicUrl)
.uploadProgressBar(uploadProgressBar)
.setMultipartParameter("goop", "noop")
.setMultipartFile("myImageName", "image/*", myImage)
.asJsonObject()
.setCallback(...)
}
I am trying to put an image on my fragment, but the image is not showing up. I am certain that it was working just yesterday but now it is not. Any help is appreciated.
This code is in my Fragment:
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
mUser = (User) getArguments().getSerializable(ARGS_USER);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View v = inflater.inflate(R.layout.fragment_picture_picker, container, false);
mImageView = v.findViewById(R.id.imageView);
mSelectImageButton = v.findViewById(R.id.select_image);
mSelectImageButton.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(intent, IMG_REQUEST);
}
});
return v;
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data){
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == IMG_REQUEST && resultCode == Activity.RESULT_OK && data != null){
Uri path = data.getData();
try {
bitmap = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), path);
mImageView.setImageBitmap(bitmap);
mImageView.setVisibility(View.VISIBLE);
mUser.setProfilePicture(bitmap);
}catch(IOException e){
e.printStackTrace();
}
}
}
Actually you are not using the Volley. Please change the heading of your question. You are accessing the Gallery and showing the image inside the imageView. Use the below code for accessing the image from camera as well as gallery.
if (action.equals("CAMERA")) {
if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
// Check Permissions Now
ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.CAMERA}, ACTION_REQUEST_CAMERA);
} else {
openCamera();
}
} else if (action.equals("GALLERY")) {
if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
// Check Permissions Now
ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, ACTION_REQUEST_GALLERY);
} else {
openGallery();
}
}
private void openCamera(){
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
getActivity().startActivityForResult(cameraIntent, ACTION_REQUEST_CAMERA);
}
private void openGallery(){
Intent galleryIntent = new Intent(Intent.ACTION_GET_CONTENT);
galleryIntent.setType("image/*");
Intent chooser = Intent.createChooser(galleryIntent, "Choose a Picture");
getActivity().startActivityForResult(chooser, ACTION_REQUEST_GALLERY);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
System.out.println("OnActivityResult");
System.out.println("resultCode: "+resultCode+"\n"+"requestCode: "+requestCode);
ImageOperations operations = new ImageOperations();
if (resultCode == RESULT_OK) {
if (requestCode == ACTION_REQUEST_GALLERY) {
System.out.println("select file from gallery ");
Uri selectedImageUri = data.getData();
renderProfileImage(selectedImageUri,operations);
} else if (requestCode == ACTION_REQUEST_CAMERA) {
System.out.println("select file from camera ");
Bitmap photo = (Bitmap) data.getExtras().get("data");
String name = "profile_pic.png";
operations.saveImageToInternalStorage(photo,getActivity(),name);
profile_image.setImageBitmap(photo);
}
}
}
private void renderProfileImage(Uri selectedImageUri,ImageOperations operations) {
Bitmap bitmap = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), selectedImageUri);
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 50, bytes);
String name = "profile_pic.png";
operations.saveImageToInternalStorage(bitmap,getActivity(),name);
profile_image.setImageBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
}
private class ImageOperations {
public boolean saveImageToInternalStorage(Bitmap image, Context context, String name) {
try {
// Use the compress method on the Bitmap object to write image to
// the OutputStream
FileOutputStream fos = context.openFileOutput("profile_pic.png", Context.MODE_PRIVATE);
// Writing the bitmap to the output stream
image.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.close();
return true;
} catch (Exception e) {
Log.e("saveToInternalStorage()", e.getMessage());
return false;
}
}
public Bitmap getThumbnail(Context context,String filename) {
String fullPath = Environment.getDataDirectory().getAbsolutePath();
Bitmap thumbnail = null;
// Look for the file on the external storage
try {
if (isSdReadable() == true) {
thumbnail = BitmapFactory.decodeFile(fullPath + "/" + filename);
}
} catch (Exception e) {
Log.e("Image",e.getMessage());
}
// If no file on external storage, look in internal storage
if (thumbnail == null) {
try {
File filePath = context.getFileStreamPath(filename);
FileInputStream fi = new FileInputStream(filePath);
thumbnail = BitmapFactory.decodeStream(fi);
} catch (Exception ex) {
Log.e("getThumbnail()", ex.getMessage());
}
}
return thumbnail;
}
public boolean isSdReadable() {
boolean mExternalStorageAvailable = false;
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
// We can read and write the media
mExternalStorageAvailable = true;
Log.i("isSdReadable", "External storage card is readable.");
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
// We can only read the media
Log.i("isSdReadable", "External storage card is readable.");
mExternalStorageAvailable = true;
} else {
// Something else is wrong. It may be one of many other
// states, but all we need to know is we can neither read nor write
mExternalStorageAvailable = false;
}
return mExternalStorageAvailable;
}
}
action is like what you want to do. ACTION_REQUEST_GALLERY and ACTION_REQUEST_CAMERA use some integer constants like 100 and 101. profileImage is your ImageView.
Hi i am working in app were user can select image when he is registering an account. I am able to get image on lollipop but when i am testing it in marshmallow then i am not getting file and its name, I am able to ask permission from user and when i am selecting image from gallery i am not getting any file or its name
This is my Code
select_image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(Build.VERSION.SDK_INT >=23) {
if (checkPermission()){
Intent intent = new Intent();
intent.setType("*/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Picture"), SELECT_PICTURE);
}else{
requestPermission();
}
}else{
Intent intent = new Intent();
intent.setType("*/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Picture"), SELECT_PICTURE);
}
}
});
My Permissions
private boolean checkPermission() {
int result = ContextCompat.checkSelfPermission(Register.this, Manifest.permission.READ_EXTERNAL_STORAGE );
if (result == PackageManager.PERMISSION_GRANTED) {
return true;
} else {
return false;
}
}
private void requestPermission() {
if (ActivityCompat.shouldShowRequestPermissionRationale(Register.this, android.Manifest.permission.READ_EXTERNAL_STORAGE)) {
Toast.makeText(Register.this, "Write External Storage permission allows us to access images. Please allow this permission in App Settings.", Toast.LENGTH_LONG).show();
} else {
ActivityCompat.requestPermissions(Register.this, new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String permissions[], #NonNull int[] grantResults) {
if(requestCode == PERMISSION_REQUEST_CODE){
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "Accepted", Toast.LENGTH_SHORT).show();
Intent intent = new Intent();
intent.setType("*/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Picture"), SELECT_PICTURE);
} else {
Log.e("value", "Permission Denied, You cannot use local drive .");
}
}
}
After Selecting Image
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
if (requestCode == SELECT_PICTURE) {
filePath = data.getData();
if (null != filePath) {
try {
bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), filePath);
// img.setImageBitmap(bitmap);
if (filePath.getScheme().equals("content")) {
try (Cursor cursor = getContentResolver().query(filePath, null, null, null, null)) {
if (cursor != null && cursor.moveToFirst()) {
file_name = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
Toast.makeText(this, file_name, Toast.LENGTH_SHORT).show();
img_name.setText(file_name);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
I am not getting why its not working in marshmallow even i have given permissions
I solved it.
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
if (requestCode == SELECT_PICTURE) {
filePath = data.getData();
if (null != filePath) {
try {
bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), filePath);
// img.setImageBitmap(bitmap);
if (filePath.getScheme().equals("content")) {
try (Cursor cursor = getContentResolver().query(filePath, null, null, null, null)) {
if (cursor != null && cursor.moveToFirst()) {
file_name = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
Toast.makeText(this, file_name, Toast.LENGTH_SHORT).show();
img_name.setText(file_name);
}
}
}else {
String path= data.getData().getPath();
file_name=path.substring(path.lastIndexOf("/")+1);
img_name.setText(file_name);
Toast.makeText(this, file_name, Toast.LENGTH_SHORT).show();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
When i was selecting file , then i was not going to this condition
if (filePath.getScheme().equals("content"))
so in else condition i have given this
String path= data.getData().getPath();
file_name=path.substring(path.lastIndexOf("/")+1);
img_name.setText(file_name);
Toast.makeText(this, file_name, Toast.LENGTH_SHORT).show();
To get image from gallery on any api level then follow this :
Copy and paste all 4 function to your activity
And call this to open gallery galleryPermissionDialog();
Variable used
final private int REQUEST_CODE_ASK_PERMISSIONS = 123;
protected static final int REQUEST_CODE_MANUAL = 5;
Permission need to add for lower than marshmallow
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Function 1:
void openGallry() {
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");
startActivityForResult(photoPickerIntent, 1);
}
Function 2 :
void galleryPermissionDialog() {
int hasWriteContactsPermission = ContextCompat.checkSelfPermission(ActivityProfile.this,
android.Manifest.permission.READ_EXTERNAL_STORAGE);
if (hasWriteContactsPermission != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(ActivityProfile.this,
new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE},
REQUEST_CODE_ASK_PERMISSIONS);
return;
} else {
openGallry();
}
}
Function 3 :
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE_ASK_PERMISSIONS: {
Map<String, Integer> perms = new HashMap<String, Integer>();
// Initial
perms.put(android.Manifest.permission.READ_EXTERNAL_STORAGE, PackageManager.PERMISSION_GRANTED);
// Fill with results
for (int i = 0; i < permissions.length; i++)
perms.put(permissions[i], grantResults[i]);
// Check for READ_EXTERNAL_STORAGE
boolean showRationale = false;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
if (perms.get(android.Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
// All Permissions Granted
galleryPermissionDialog();
} else {
showRationale = ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.READ_EXTERNAL_STORAGE);
if (showRationale) {
showMessageOKCancel("Read Storage Permission required for this app ",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
galleryPermissionDialog();
}
});
} else {
showMessageOKCancel("Read Storage Permission required for this app ",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(ActivityProfile.this, "Please Enable the Read Storage permission in permission", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivityForResult(intent, REQUEST_CODE_MANUAL);
}
});
//proceed with logic by disabling the related features or quit the app.
}
}
} else {
galleryPermissionDialog();
}
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
Function 4 :
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
switch (requestCode) {
case 1:
if (resultCode == RESULT_OK) {
try {
final Uri imageUri = imageReturnedIntent.getData();
/* final InputStream imageStream = getContentResolver().openInputStream(imageUri);
final Bitmap selectedImage = BitmapFactory.decodeStream(imageStream);
img_profile.setImageBitmap(selectedImage);*/
String[] filePathColumn = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(imageUri, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String picturePath = cursor.getString(columnIndex);
cursor.close();
pictureFile = saveBitmapToFile(new File(picturePath));
Picasso.with(getApplicationContext()).load(new File(picturePath)).transform(new CircleTransform()).into(imgProfile);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Function 5 :
public void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) {
new AlertDialog.Builder(ActivityProfile.this)
.setTitle(R.string.app_name)
.setMessage(message)
.setCancelable(false)
.setPositiveButton("OK", okListener)
.setNegativeButton("Cancel", null)
.create()
.show();
}
file/* is not a valid MIME type. You should use / if you want to support any type of file. The files you see are unselectable because they are not of the correct MIME type.
With the introduction of virtual files in Android 7.0 (files that don't have a bytestream and therefore cannot be directly uploaded), you should most definitely add CATEGORY_OPENABLE to your Intent:
https://developer.android.com/about/versions/nougat/android-7.0.html#virtual_files
https://developer.android.com/reference/android/content/Intent.html#CATEGORY_OPENABLE
private void showFileChooser() {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
//sets the select file to all types of files
intent.setType("*/*");
// Only get openable files
intent.addCategory(Intent.CATEGORY_OPENABLE);
//starts new activity to select file and return data
startActivityForResult(Intent.createChooser(intent,
"Choose File to Upload.."), PICK_FILE_REQUEST);
}
public String getFileName(Uri uri) {
String result = null;
if (uri.getScheme().equals("content")) {
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
try {
if (cursor != null && cursor.moveToFirst()) {
result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
}
} finally {
cursor.close();
}
}
if (result == null) {
result = uri.getPath();
int cut = result.lastIndexOf('/');
if (cut != -1) {
result = result.substring(cut + 1);
}
}
return result;
}
String filename =getFileName(yourfileuri);
I'm working on an app, in witch i need to store more than 1600 images (.PNG) in BLOB format. Each image has nearly 230KB in size.
What i want to do, is to compress images to someting below 20KB. So as a result the whole size of images will be around 32 MB (1600 x 20KB) and the final apk size will be reduced.
To explain more : what i want to do is to compress images from 230KB to under 20KB to save more space in the database. the database will be filled with data and images before integrating it in the apk.
So if i compressed images stored in database. the database size will reduce. and it will not take a lot of space inside APK
Any suggestions on how to do that ?
NOTE : the Database will be filled with information before integrating in the app.
I think it would be the best to store those images on server, and once user downloads your app you should transfer images to app.
1600 is really a big number for app before it's installed...
I do not know if this is the best way to save storage space using SQLite and I am still looking for it, but here we go.
You can select the source of your image, such as gallery or camera and below is the code.
private void selectProductImage() {
final CharSequence[] itens = {"Use Camera", "Gallery", "Cancel"};
AlertDialog.Builder builder = new AlertDialog.Builder(this,R.style.AlertDialog);
builder.setItems(itens, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (itens[which].equals("Use Camera")) {
Toast.makeText(YourActivity.this, "Use Camera", Toast.LENGTH_SHORT).show();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{Manifest.permission.CAMERA}, MY_CAMERA_PERMISSION_CODE);
} else {
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);
}
} else if (itens[which].equals("Gallery")) {
Toast.makeText(YourActivity.this, "Gallery", Toast.LENGTH_SHORT).show();
Intent galleryIntent = new Intent();
galleryIntent.setAction(Intent.ACTION_GET_CONTENT);
galleryIntent.setType("image/*");
startActivityForResult(galleryIntent, REQUEST_GALLERY_PHOTO);
} else if (itens[which].equals("Cancel")) {
dialog.dismiss();
}
}
});
builder.show();
}
Maybe you need permission to use the camera
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == MY_CAMERA_PERMISSION_CODE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//Toast.makeText(this, "camera permission granted", Toast.LENGTH_LONG).show();
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);
} else {
Toast.makeText(this, "camera permission denied", Toast.LENGTH_LONG).show();
}
return;
}
}
Here is how to handle the image from the source you selected.
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK) {
Bitmap bitmap = Bitmap.createScaledBitmap((Bitmap) data.getExtras().get("data"),96, 96, true);
mProductImage.setImageBitmap(bitmap);
isPriviteImage = true;
}
if (requestCode == REQUEST_GALLERY_PHOTO && resultCode == RESULT_OK && data != null) {
//mProductImage.setImageURI(data.getData());
// INSERT IMAGE INTO SQLite
Uri uri = data.getData();
try {
InputStream inputStream = getContentResolver().openInputStream(uri);
Bitmap bitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeStream(inputStream),96, 96, true);
mProductImage.setImageBitmap(bitmap);
isPriviteImage = true;
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
As you can notice in my example, there is no place to save the image case you selected camera and I placed the image on an ImageView variable named mProductImage.
From now, you can use a Button to save the image in your SQLite Database. Here is the function you can use for it.
private void saveImage() {
productTablePath = Environment.getExternalStorageDirectory()+"/YourAditionalPath/";
ProductDatabaseHelper productDatabaseHelper = new ProductDatabaseHelper(getApplicationContext(), "dbname.db", productTablePath);
productListTable = productDatabaseHelper.getWritableDatabase();
productRepository = new ProductRepository(productListTable);
try {
if (isPriviteImage) {
productRepository.addProduct(imageViewToByte(mProductImage));
isPriviteImage = false;
} else {
productRepository.addProduct(null);
}
mProductImage.setImageResource(R.drawable.shopping_cart_black_48dp);
} catch (Exception e) {
e.printStackTrace();
}
}
Where imageViewToByte functon is:
private byte[] imageViewToByte(CircleImageView image) {
Bitmap bitmap = ((BitmapDrawable)image.getDrawable()).getBitmap();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG,100,stream);
byte[] byteArray = stream.toByteArray();
return byteArray;
}
Now you need to implement the SQLiteOpenHelper. You need to create a new class for this. The java file name I used for this was ProductDatabaseHelper.java.
public class ProductDatabaseHelper extends SQLiteOpenHelper {
private static int dbVersion = 1;
public ProductDatabaseHelper(Context context, String name, String storageDirectory) {
super(context, storageDirectory+name, null, dbVersion);
}
#Override
public void onCreate(SQLiteDatabase db) {
StringBuilder sql = new StringBuilder();
sql.append("CREATE TABLE IF NOT EXISTS PRODUCTLIST (");
sql.append(" IMAGE BLOB,");
db.execSQL(sql.toString());
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
Now you need to implement your CRUD (Create new item, Read, Update and Delete).
public class ProductRepository {
SQLiteDatabase instance;
public ProductRepository(SQLiteDatabase instance) {
this.instance = instance;
}
public void addProduct(byte[] image){
ContentValues contentValues = new ContentValues();
contentValues.put("IMAGE",image);
instance.insertOrThrow("PRODUCTLIST",null, contentValues);
}
}
It is important to mention that the compression of the image was made in the onActivityResult() for both source image (camera and gallery).
with the command:
Bitmap bitmap = Bitmap.createScaledBitmap(capturedImage, width, height, true);
Besides that, here is a link where we can read a little bit about compression.
https://androidwave.com/capture-image-from-camera-gallery/
If you have a better way to compress images to save in SQLite Database, please post your code here!
I'm trying to make an app that uses the camera to take photos and sends this to my NAS, I managed to do create an app through a tutorial, which takes a picture, saves the picture and shows it onscreen. Another tutorial shows me how to upload a "selected" image by pressing an "extra" button on the screen, it's just that I want to get rid of this step and instead of showing the picture, it directly sends the picture to my NAS.
The current app I created:
package com.deshpande.camerademo;
public class MainActivity extends AppCompatActivity {
private Button takePictureButton;
private ImageView imageView;
private Uri file;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
takePictureButton = (Button) findViewById(R.id.button_image);
imageView = (ImageView) findViewById(R.id.imageview);
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
takePictureButton.setEnabled(false);
ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE }, 0);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == 0) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED
&& grantResults[1] == PackageManager.PERMISSION_GRANTED) {
takePictureButton.setEnabled(true);
}
}
}
public void takePicture(View view) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
file = Uri.fromFile(getOutputMediaFile());
intent.putExtra(MediaStore.EXTRA_OUTPUT, file);
startActivityForResult(intent, 100);
}
private static File getOutputMediaFile(){
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "WedCam");
if (!mediaStorageDir.exists()){
if (!mediaStorageDir.mkdirs()){
Log.d("WedCam", "failed to create directory");
return null;
}
}
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
return new File(mediaStorageDir.getPath() + File.separator +
"IMG_"+ timeStamp + ".jpg");
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 100) {
if (resultCode == RESULT_OK) {
try {
final FTPClient client = new FTPClient();
final File image = new File(file.getPath());
final FileInputStream fis = new FileInputStream(image);
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
client.connect("ftp://127.0.0.1:2221");
client.login("francis", "francis");
client.storeFile(image.getName(), fis);
client.logout();
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}
Thanks to #Matthias F. I got it all working, this guy is great!
You need to use your saved URI from the camera for the FileInputStream. Try it with this:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 100) {
if (resultCode == RESULT_OK) {
try {
final FTPClient client = new FTPClient();
final File image = new File(file.getPath());
final FileInputStream fis = new FileInputStream(image);
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
client.connect("127.0.0.1", 2221);
client.login("francis", "francis");
client.setFileType(FTP.BINARY_FILE_TYPE);
client.storeFile(image.getName(), fis);
client.logout();
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Now the FileInputStream points to the created image.
EDIT:
The problem was that the upload was executed on the ui thread and that is not allowed in android. Now a new thead is created for the upload process. Also I forgot to say that you need to access a android permission for using network functionalities. So you need to set
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> in the AndroidManifest.xml.