user8934311
user8934311

Reputation:

How can I implement onActivityResult inside an Adapter?

Can someone explain me, with some code snippets, how we can recover the result of onActivityResult inside an Adapter? I've read some about interfaces, but i couldn't be able trying implementing this.Thanks in advance!

Example: Inside the adapter i have a ViewHolder, inside which is an ImageView.An event clicking on this ImageView starts an startActivityForResult.But in the same adapter i need to recover the result by onActivityResult method.

How to do with the following:

MainActivity:

public class MainActivity extends AppCompatActivity {

    private RecyclerView recyclerView;
    private List<Filme> listaFilmes = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        recyclerView = findViewById(R.id.recyclerView);

        //Listagem de filmes
        this.criarFilmes();

        //Configurar adapter
        final Adapter adapter = new Adapter(listaFilmes,getApplicationContext(),MainActivity.this);


        //Configurar Recyclerview
        //Para mostrar na horizontal: new LinearLayoutManager(getApplicationContext(),LinearLayoutManager.HORIZONTAL,false);
        RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext(),LinearLayoutManager.HORIZONTAL,false);
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.setHasFixedSize(true);
        recyclerView.addItemDecoration( new DividerItemDecoration(this, LinearLayout.VERTICAL));
        recyclerView.setAdapter(adapter);

    }

    public void criarFilmes(){
        Filme filme = new Filme("Homem Aranha - De volta ao lar","Aventura","2017");
        this.listaFilmes.add( filme );

    }
}

Adapter:

public class Adapter extends RecyclerView.Adapter<Adapter.MyViewHolder> {

    private List<Filme> listaFilmes;
    private Context context;
    private Activity activity;
    private ImageView imagem;
    private Uri photoURI;
    Uri filePath;
    String mCurrentPhotoPath;
    static final int REQUEST_TAKE_PHOTO = 1;



    public Adapter(List<Filme> listaFilmes, Context context,Activity activity) {
        this.listaFilmes = listaFilmes;
        this.context = context;
        this.activity = activity;
    }

    //Aqui ele cria apenas a visualização
    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemLista = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.adapter_lista, parent, false);

        return new MyViewHolder(itemLista);
    }

    //A exibição dos itens ocorre aqui
    @Override
    public void onBindViewHolder(MyViewHolder holder, final int position) {

        final Filme filme = listaFilmes.get(position);
        /*holder.titulo.setText(filme.getTituloFilme());
        holder.genero.setText(filme.getGenero());
        holder.ano.setText(filme.getAno());*/
        holder.imagem.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                Toast.makeText(context, "imagem removida", Toast.LENGTH_SHORT).show();
                listaFilmes.remove(position);
                notifyDataSetChanged();
                return false;
            }
        });
        holder.imagem.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(context, "imagem clicada", Toast.LENGTH_SHORT).show();
                listaFilmes.add(position+1,filme);
                notifyDataSetChanged();
                selectImage();


            }
        });
    }

    //Retorna a quantidade de itens que serão exibidos
    @Override
    public int getItemCount() {
        return listaFilmes.size();
    }


    public class MyViewHolder extends RecyclerView.ViewHolder {

        /*TextView titulo;
        TextView ano;
        TextView genero;*/
        ImageView imagem;

        public MyViewHolder(View itemView) {
            super(itemView);

            imagem = itemView.findViewById(R.id.image_id);
            /*titulo = itemView.findViewById(R.id.textTitulo);
            ano    = itemView.findViewById(R.id.textAno);
            genero = itemView.findViewById(R.id.textGenero);*/
        }
    }

    /*Função seleciona foto da galeria ou tira foto*/
    public void selectImage() {

        final CharSequence[] options = { "Take Photo", "Choose from Gallery","Cancel" };
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setTitle("Add Photo!");
        builder.setItems(options, new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int item) {
                if (options[item].equals("Take Photo"))
                {
                    dispatchTakePictureIntent(activity);
                }
                else if (options[item].equals("Choose from Gallery"))
                {
                    Intent intent = new   Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                    ((Activity) context).startActivityForResult(intent, 2);
                }
                else if (options[item].equals("Cancel")) {
                    dialog.dismiss();
                }
            }
        });
        builder.show();
    }

    //ativa a camera para tirar foto
    public void dispatchTakePictureIntent(Activity currentActivity) {
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        //Ensure that there`s a camera activity to handle the intent
        if(takePictureIntent.resolveActivity( context.getApplicationContext().getPackageManager() ) != null ){ //getActivity
            //Create the File where the photo should go
            File photoFile = null;
            try{
                photoFile = createImageFile(currentActivity);
            }catch(IOException ex){
                //Error occurred while creating the File
                ex.printStackTrace();

            }
            //Continue only if the File was successfully created
            if(photoFile != null){
                Log.i("ENTFR11","photofile:"+ photoFile); //    /storage/emulated/0/Android/data/com.droidelivery.droidelivery/files/Pictures/JPEG_20171010_205010_1588304974.jpg
                photoURI = FileProvider.getUriForFile(context.getApplicationContext(), //getActivity
                        "com.example.lucas.recyclerview.fileprovider",
                        photoFile);
                Log.i("ENTFR12","photofURI:"+ photoURI); //    content://com.example.android.fileprovider/my_images/JPEG_20171010_205010_1588304974.jpg
                takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI); //ESTUDAR ESSA LINHA ESTÄ COM PROBLEMA.COMO RECUPERAR EXTRA_OUTPUT
                Log.i("ENTFR13","photoURI: " + photoURI);
                ((Activity) context).startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
            }
        }
    }

    //Create a collision-resistant file name
    public File createImageFile(Activity currentActivity) throws IOException {
        //Create an image file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault() ).format(new Date());
        String imageFileName = "JPEG_" + timeStamp + "_";
        File storageDir = currentActivity.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        File image = File.createTempFile(
                imageFileName, /*prefix*/
                ".jpg",        /*suffix*/
                storageDir     /*directory*/
        );

        //Save a file: path for use with ACTION_VIEW intents
        mCurrentPhotoPath = image.getAbsolutePath();
        return image;
    }

    public void setPic() {
        // Get the dimensions of the View

        int targetW = imagem.getWidth();
        int targetH = imagem.getHeight();

        // Get the dimensions of the bitmap
        BitmapFactory.Options bmOptions = new BitmapFactory.Options();
        bmOptions.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
        int photoW = bmOptions.outWidth;
        int photoH = bmOptions.outHeight;

        // Determine how much to scale down the image
        int scaleFactor = Math.min(photoW/targetW, photoH/targetH);

        // Decode the image file into a Bitmap sized to fill the View
        bmOptions.inJustDecodeBounds = false;
        bmOptions.inSampleSize = scaleFactor;
        bmOptions.inPurgeable = true;

        Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
        imagem.setImageBitmap(bitmap);

    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {

        if (requestCode == REQUEST_TAKE_PHOTO && resultCode == RESULT_OK ) { //lembrar que activity que requisita foto nao retorna necessariamente uma URI!!!
            //filePath = data.getData();
            //filePath = photoURI;
            setPic();
        }
        if(requestCode == 2 && resultCode == RESULT_OK && data != null){
            Toast.makeText(context, "requestCode == 2", Toast.LENGTH_SHORT).show();
            try {
                //getting image from gallery
                Uri selectedImage = data.getData();
                Log.i("SSS","selectedImage: " + selectedImage);
                Bitmap bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), selectedImage);//getContext

                imagem.setImageBitmap(bitmap);
            }catch(Exception e){
                e.printStackTrace();
            }

        }
    }
}

Upvotes: 1

Views: 7199

Answers (2)

OneCricketeer
OneCricketeer

Reputation: 191681

You could define an interface...

public interface OnIntentReceived {
  void onIntent(Intent i, int resultCode);
}

Implement interface on the adapter. Note: You only need a Context in an adapter, not also an Activity instance

public class MyAdapter extends RecyclerView.Adapter<T> implements OnIntentReceived {

   private Context mContext;

   @Override public void onIntent(Intent i, int resultCode) {
      // TODO: Handle here
   }

   // Somewhere in here, mContext.startActivityForResult(MyActivity.REQUEST_CODE);

}

In the activity, define the adapter and forward the intent result to the callback interface

public class MyActivity extends AppCompatActivity {

  public static final int REQUEST_CODE = 101;

  private MyAdapter mAdapter;
  private List data = new ArrayList();
  private OnIntentReceived mIntentListener;

  @Override protected void onCreate(Bundle b) {
     ... 

     mAdapter = new MyAdapter(this, data);
     mIntentListener = mAdapter;
  }

  @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_CODE) {
        if (mIntentListener != null) {
          mIntentListener.onIntent(data, resultCode);
        }
    }
  }
}

Upvotes: 3

Khalid Taha
Khalid Taha

Reputation: 3313

The answer of @cricket_007 is correct, but there is another way is to use Observable and Observer architecture,

The Observer in your case is the Adapter, while the Observable is the object that will hold the data retrieved from the onActivityResult through your activity: 1- Create the Observable:

public class MyObservable extends Observable {
    private static MyObservable instance = null;
    private MyObservable() {
    }
    public static MyObservable getInstance() {
        if(instance == null) {
            instance = new MyObservable() ;
        }
        return instance;
    }
    public void sendData(Object data) {
        setChanged();
        notifyObservers(data);
    }
}

2- Add it to the Observer class (the adapter)

public class MyAdapter extends BaseAdapter implements Observer {
// add the observer to the observable through:
MyObservable.getInstance().addObserver(this);
...
@Override
public void update(Observable observable, Object o) {
    if(observable instanceof MyObservable) {
        // do what you need here
    }
}

3- Call the Observer from your activityResult:

@Override
public void oActivityResult( ... ) {
    MyObserver.getInstance().sendData(yourData);
}

Upvotes: 1

Related Questions