Issue
Hello Guys I am new to Android Studio so the problem is that I have 10 screen for my app. On screen 7 I use startActivityForResult to call screen 8 which input some data and images from gallery and send back the response to screen 7. The screen 7 use recycle view which display that entries. I have put a click listener on specific row which opens up screen 10 which displays the data and image but screen 10 shows other data but on setting image uri it crashes. I am using parecelable which has all the fields including image uri. I don't why it crashes on one screen but not the other
**Screen-7**
package com.hamza.i180502;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
public class Screen_7 extends AppCompatActivity implements MyAdapter.CallbackInterface{
List<Ad> ls;
Button add_data;
ImageView back;
RecyclerView rv;
MyAdapter adapter;
TextView dummy;
static int MY_REQUEST=1001;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_screen7);
add_data=findViewById(R.id.add_data);
back=findViewById(R.id.back);
rv=findViewById(R.id.rv);
dummy=findViewById(R.id.dummy);
ls=new ArrayList<>();
back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
add_data.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent myIntent = new Intent(Screen_7.this,Screen_8.class);
startActivityForResult(myIntent,1);
//startActivity(myIntent);
}
});
adapter=new MyAdapter(Screen_7.this,ls);
rv.setLayoutManager(new GridLayoutManager(Screen_7.this, 3));
rv.setAdapter(adapter);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case (1): {
if (resultCode == RESULT_OK) {
Ad dene = data.getParcelableExtra("MyClass");
ls.add(new Ad(dene.getImage(), dene.getName(), dene.getPrice(), dene.getLocation(), dene.getDesc(), dene.getTags()));
adapter.notifyDataSetChanged();
}
if (resultCode == RESULT_CANCELED) {
Toast.makeText(Screen_7.this, "Nothing Entered", Toast.LENGTH_LONG);
}
}
break;
case (1001): {
if (resultCode == RESULT_OK) {
Ad dene = data.getParcelableExtra("screen9");
String position=data.getStringExtra("Position9");
ls.remove(Integer.parseInt(position));
ls.add(new Ad(dene.getImage(), dene.getName(), dene.getPrice(), dene.getLocation(), dene.getDesc(), dene.getTags()));
adapter.notifyDataSetChanged();
}
if (resultCode == RESULT_CANCELED) {
Toast.makeText(Screen_7.this, "Nothing Entered", Toast.LENGTH_LONG);
}
}
break;
}
}
@Override
public void onHandleSelection(int position, Ad text) {
Intent secondActivity = new Intent(Screen_7.this, Screen_9.class);
secondActivity.putExtra("viewClass1",text);
secondActivity.putExtra("Position", String.valueOf(position));
secondActivity.putExtra("image",String.valueOf(text.getImage()));
startActivityForResult(secondActivity, MY_REQUEST);
}
}
**Screen10**
package com.hamza.i180502;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
public class Screen_10 extends AppCompatActivity {
TextView name,price,tags,description,location;
ImageView upload_image;
ImageView back;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_screen10);
Ad ad = (Ad)getIntent().getParcelableExtra("viewClass");
upload_image=findViewById(R.id.image_10);
name=findViewById(R.id.name);
location=findViewById(R.id.location);
description=findViewById(R.id.description);
tags=findViewById(R.id.tags);
price=findViewById(R.id.price);
name.setText(ad.getName());
description.setText(ad.getDesc());
price.setText(ad.getPrice());
tags.setText(ad.getTags());
location.setText(ad.getLocation());
Uri im= (Uri)ad.getImage();
Log.d("Var", String.valueOf(im));
upload_image.setImageURI(im);
back=findViewById(R.id.back);
back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
}
}
**MyAdapter**
package com.hamza.i180502;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
Context c;
List<Ad> values;
private CallbackInterface mCallback;
public interface CallbackInterface{
void onHandleSelection(int position, Ad text);
}
public MyAdapter(Context c, List<Ad> values) {
this.c = c;
this.values = values;
// .. Attach the interface
try{
mCallback = (CallbackInterface) c;
}catch(ClassCastException ex){
//.. should log the error or throw and exception
Log.e("MyAdapter","Must implement the CallbackInterface in the Activity", ex);
}
}
@NonNull
@Override
public MyAdapter.MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View row= LayoutInflater.from(c).inflate(R.layout.ad, parent,false);
return new MyViewHolder(row);
}
@Override
public void onBindViewHolder(@NonNull MyAdapter.MyViewHolder holder, @SuppressLint("RecyclerView") int position) {
holder.name.setText(values.get(position).getName());
holder.price.setText(values.get(position).getPrice());
holder.location.setText(values.get(position).getLocation());
holder.imageView.setImageURI(values.get(position).getImage());
values.get(position).setId(position);
holder.imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent myIntent=new Intent(c,Screen_10.class);
Ad ad=values.get(holder.getAdapterPosition());
myIntent.putExtra("viewClass",(Ad)ad);
c.startActivity(myIntent);
}
});
holder.imageView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
if(mCallback != null){
mCallback.onHandleSelection(position, values.get(position));
}
return false;
}
});
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) {
if (resultCode == 1) {
Ad dene= data.getParcelableExtra("screen9");
Log.d("Description",dene.getDesc());
values.remove(dene.getId());
}
if (resultCode == 0) {
Toast.makeText(((Activity) c),"Nothing Entered",Toast.LENGTH_LONG);
}
}
}
@Override
public int getItemCount() {
return values.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView name,price,location;
ImageView imageView;
public MyViewHolder(@NonNull View row) {
super(row);
imageView=row.findViewById(R.id.image);
name=row.findViewById(R.id.name);
location=row.findViewById(R.id.location);
price=row.findViewById(R.id.price);
}
}
}
**Ad(Object)**
package com.hamza.i180502;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
public class Ad implements Parcelable{
public int getId() {
return id;
}
public void setId(int id){
this.id=id;
}
public static Creator<Ad> getCREATOR() {
return CREATOR;
}
private int id;
public Ad(Uri image, String name, String price, String location, String desc,String tags) {
this.image = image;
this.name = name;
this.price = price;
this.location = location;
this.desc = desc;
this.tags = tags;
}
public Ad(){
}
protected Ad(Parcel in) {
image = in.readParcelable(Uri.class.getClassLoader());
name = in.readString();
price = in.readString();
tags = in.readString();
location = in.readString();
desc = in.readString();
}
public static final Creator<Ad> CREATOR = new Creator<Ad>() {
@Override
public Ad createFromParcel(Parcel in) {
return new Ad(in);
}
@Override
public Ad[] newArray(int size) {
return new Ad[size];
}
};
public Uri getImage() {
return image;
}
public String getName() {
return name;
}
public String getPrice() {
return price;
}
public String getLocation() {
return location;
}
public String getDesc() {
return desc;
}
private Uri image;
private String name , price, tags,location,desc;
public String getTags() {
return tags;
}
public void setTags(String tags) {
this.tags = tags;
}
public void setImage(Uri image) {
this.image = image;
}
public void setName(String name) {
this.name = name;
}
public void setPrice(String price) {
this.price = price;
}
public void setLocation(String location) {
this.location = location;
}
public void setDesc(String desc) {
this.desc = desc;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeParcelable(image, i);
parcel.writeString(name);
parcel.writeString(price);
parcel.writeString(tags);
parcel.writeString(location);
parcel.writeString(desc);
}
}
**Manifest**
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.hamza.i180502">
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.I180502">
<activity
android:name=".Screen_10"
android:exported="true" />
<activity
android:name=".Screen_8"
android:exported="true" />
<activity
android:name=".Screen_9"
android:exported="true" />
<activity
android:name=".Screen_7"
android:exported="true" />
<activity
android:name=".Screen_6"
android:exported="true" />
<activity
android:name=".Screen_5"
android:exported="true" />
<activity
android:name=".Screen_4"
android:exported="true" />
<activity
android:name=".Screen_3"
android:exported="true" />
<activity
android:name=".Screen_2"
android:exported="true" />
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Solution
This is a common problem people face when using URIs. URIs are temporary addresses to a image/file. They are similar to a link you click to open a website i.e.url. Once a session ends the URI to access a file/image expires and using it to access a file again crashes the app and gives a permission denial exception. This is the same in your case when you try to access the uri again it crashes.
Solution
once you get the uri in screen_8 store the image in the app's internal storage using bitmap and then generate a new uri for the image stored in the inernal storage with Uri.fromFile(file);. Now use this new generated uri in any activity in the app. This should solve your problem. Good luck and Happy coding!
Answered By - umar Ali
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.