I am designing my first Android App and I am facing the following problem:
When I access my gallery by pressing a button, the images I can use are those that come from the "Download" and "Screenshot" directories. The rest fail me.
Also, this only works when I access from "Gallery" and not "Photos". My Android version is 4.3 (I mention it in case it has any relevance, since the code in some parts needs a higher one)
I am attaching a picture to make it all clearer:
As for the code (it might be a bit chaotic. Like I said, I'm new to this):
import static android.Manifest.permission.CAMERA;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
public class RegistroActivity extends AppCompatActivity {
private static String APP_DIRECTORY = "MyPictureApp/";
private static String MEDIA_DIRECTORY = APP_DIRECTORY + "PictureApp";
private final int MY_PERMISSIONS = 100;
private final int SELECT_PICTURE = 300;
private ImageView mSetImage;
private Button mOptionButton;
private RelativeLayout mRlView;
private String mPath;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_registro);
Button bt_listo = (Button) findViewById(R.id.bt_listo);
bt_listo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v){
Toast toast1 =
Toast.makeText(getApplicationContext(),
"Registrado Correctamente", Toast.LENGTH_SHORT);
toast1.show();
Intent intent_registrar = new Intent(RegistroActivity.this, MainActivity.class);
startActivity(intent_registrar);
}
});
mSetImage = (ImageView) findViewById(R.id.ibt_imagen);
mOptionButton = (Button) findViewById(R.id.bt_galeria);
mRlView = (RelativeLayout) findViewById(R.id.id_registroactivity);
if(mayRequestStoragePermission())
mOptionButton.setEnabled(true);
else
mOptionButton.setEnabled(false);
mOptionButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i("X: "+ mOptionButton.getX(), "Y: " + mOptionButton.getY());
mOptionButton.setVisibility(View.GONE);
Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
intent.setType("image/*");
startActivityForResult(intent.createChooser(intent, "Seleccionar imagen"), SELECT_PICTURE);
}
});
}
@Override
public void onBackPressed(){
}
private boolean mayRequestStoragePermission() {
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
return true;
if((checkSelfPermission(WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) &&
(checkSelfPermission(CAMERA) == PackageManager.PERMISSION_GRANTED))
return true;
if((shouldShowRequestPermissionRationale(WRITE_EXTERNAL_STORAGE)) || (shouldShowRequestPermissionRationale(CAMERA))){
Snackbar.make(mRlView, "Permisos requeridos",
Snackbar.LENGTH_INDEFINITE).setAction(android.R.string.ok, new View.OnClickListener() {
@TargetApi(Build.VERSION_CODES.M)
@Override
public void onClick(View v) {
requestPermissions(new String[]{WRITE_EXTERNAL_STORAGE, CAMERA}, MY_PERMISSIONS);
}
});
}else{
requestPermissions(new String[]{WRITE_EXTERNAL_STORAGE, CAMERA}, MY_PERMISSIONS);
}
return false;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("file_path", mPath);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
mPath = savedInstanceState.getString("file_path");
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == RESULT_OK){
Uri path = data.getData();
mSetImage.setImageURI(path);
mSetImage.requestLayout();
mSetImage.getLayoutParams().height = 140;
mSetImage.getLayoutParams().width = 140;
Toast.makeText(RegistroActivity.this, "Imagen cargada", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode == MY_PERMISSIONS){
if(grantResults.length == 2 && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED){
Toast.makeText(RegistroActivity.this, "Permisos aceptados", Toast.LENGTH_SHORT).show();
mOptionButton.setEnabled(true);
}
}else{
showExplanation();
}
}
private void showExplanation() {
AlertDialog.Builder builder = new AlertDialog.Builder(RegistroActivity.this);
builder.setTitle("Permisos denegados");
builder.setMessage("Permisos requeridos");
builder.setPositiveButton("Aceptar", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivity(intent);
}
});
builder.setNegativeButton("Cancelar", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
finish();
}
});
builder.show();
}
}
<?xml version="1.0" encoding="utf-8"?>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/pt_alias"
android:layout_centerVertical="true"
android:hint="@string/pt_alias"
android:layout_alignLeft="@+id/bt_listo"
android:layout_alignStart="@+id/bt_listo"
android:layout_alignRight="@+id/ibt_imagen"
android:layout_alignEnd="@+id/ibt_imagen" />
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/pt_correoElectronico"
android:layout_below="@+id/pt_alias"
android:layout_alignRight="@+id/pt_alias"
android:layout_alignEnd="@+id/pt_alias"
android:hint="@string/pt_email"
android:layout_alignLeft="@+id/pt_alias"
android:layout_alignStart="@+id/pt_alias" />
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/pt_contraseña"
android:layout_below="@+id/pt_correoElectronico"
android:layout_alignRight="@+id/pt_correoElectronico"
android:layout_alignEnd="@+id/pt_correoElectronico"
android:hint="@string/pt_contraseña"
android:layout_alignLeft="@+id/pt_correoElectronico"
android:layout_alignStart="@+id/pt_correoElectronico" />
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/pt_repetirContraseña"
android:layout_below="@+id/pt_contraseña"
android:layout_alignRight="@+id/pt_contraseña"
android:layout_alignEnd="@+id/pt_contraseña"
android:hint="@string/pt_repetirPass"
android:layout_marginBottom="30dp"
android:layout_alignLeft="@+id/pt_contraseña"
android:layout_alignStart="@+id/pt_contraseña" />
<Button
android:layout_width="250dp"
android:layout_height="wrap_content"
android:id="@+id/bt_listo"
android:layout_below="@+id/pt_repetirContraseña"
android:layout_centerHorizontal="true"
android:text="@string/bt_listo"
android:clickable="true"
/>
<ImageView
android:layout_width="180dp"
android:layout_height="180dp"
android:id="@+id/logoRegistro"
android:background="@drawable/logofinal"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/ibt_imagen"
android:clickable="true"
android:layout_above="@+id/pt_alias"
android:layout_alignRight="@+id/bt_listo"
android:layout_alignEnd="@+id/bt_listo"
android:gravity="right"
/>
<Button
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/bt_galeria"
android:background="@drawable/foto"
android:layout_alignBottom="@+id/ibt_imagen"
android:layout_alignRight="@+id/ibt_imagen"
android:layout_alignEnd="@+id/ibt_imagen" />
And the error displayed:
11-13 10:35:52.826 3137-3137/mario.rankit E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.OutOfMemoryError
at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:623)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:444)
at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:832)
at android.graphics.drawable.Drawable.createFromStream(Drawable.java:783)
at android.widget.ImageView.resolveUri(ImageView.java:673)
at android.widget.ImageView.setImageURI(ImageView.java:407)
at mario.rankit.RegistroActivity.onActivityResult(RegistroActivity.java:137)
at android.app.Activity.dispatchActivityResult(Activity.java:5563)
at android.app.ActivityThread.deliverResults(ActivityThread.java:3496)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:3543)
at android.app.ActivityThread.access$1200(ActivityThread.java:159)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1364)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:176)
at android.app.ActivityThread.main(ActivityThread.java:5419)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862)
at dalvik.system.NativeStart.main(Native Method)
I was wondering if anyone knew how to fix it. All the best.
The problem related to
OutOfMemoryError
is due to the fact that it does not have the capacity to store one or several images in memory, I suggest this answer where you will get ideas to optimize your resources:The theme of the galleries created from a widget
Gallery
has always been a problem, the problems are basically related to the fact that the images, when loaded within the execution ofgetView()
, are loaded within it,ImageView
but whenImageView
it is not visible, they are not released from it , you are actually loading the images and keeping them even without being displayed.A quick fix is to remove the image from the ImageView when it is not displayed using setBackgroundDrawable() by assigning it a null value:
But there are other important considerations such as the weight of the image, on small devices sometimes it is not necessary to load a large image since its manipulation in memory is difficult and even more so if we have several instances we will cause
OutofMemory
.I suggest you review these optimization tips: Good image resolution
and in the case of your gallery I recommend using Picasso or Glide within
to load the images inside the
ImageView
, I am not recommending libraries but in this case there are 2 good options that I recommend, in fact they optimize the image that they load inside theImageView
, this results in a low memory consumption which will avoid problems related toOutofMemory
.