2016-01-02 17 views
5

Ho cercato in alto e in basso per trovare un esempio di come implementare le modifiche alle immagini del profilo all'interno della mia app. Voglio consentire alle persone di aggiungere/modificare la loro immagine del profilo utilizzando Parse.com (Simile a tutte le app di social media di oggi).Come creare un'app che consenta il caricamento/modifica delle immagini del profilo?

Ad esempio: Twitter, Facebook, Instagram e così via, tutti consentono di caricare/caricare un'immagine del profilo e quell'immagine viene salvata e può essere visualizzata in seguito.

ho avuto fortuna a trovare qualsiasi materiale che copre come fare una cosa del genere e nessun altro sembra essere capire quello che sto cercando di realizzare qui:

An Image Downloaded From Parse Stay On Screen Even After You Exit And Reopen App?

Finora nella mia app l'utente può scattare una foto con l'intento della videocamera o caricare un'immagine dalla galleria e quell'immagine viene visualizzata perfettamente in una vista dell'immagine.

Il problema è: quando esco e riapro l'app l'immagine all'interno della vista immagine non è più visualizzata (è sparita).

Come posso risolvere questo problema?

MainActivity:

 public class MainActivity extends AppCompatActivity { 

     public static final int TAKE_PIC_REQUEST_CODE = 0; 
     public static final int CHOOSE_PIC_REQUEST_CODE = 1; 
     public static final int MEDIA_TYPE_IMAGE = 2; 

     private Uri mMediaUri; 

     private TextView mChangeProfilePic; 
     protected ImageView mPreviewImageView; 
     private Button mSaveChangesBtn; 
     public ImageView mProfilePic; 


     @Override 
     protected void onCreate(Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState); 
      setContentView(R.layout.activity_main); 
      Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 
      setSupportActionBar(toolbar); 


      FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); 
      fab.setOnClickListener(new View.OnClickListener() { 
       @Override 
       public void onClick(View view) { 
        Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) 
          .setAction("Action", null).show(); 
       } 
      }); 


      //Initialize variables 
      mChangeProfilePic = (TextView) findViewById(R.id.changeProfileImageTxt); 
      mPreviewImageView = (ImageView) findViewById(R.id.profileImage); 
      mSaveChangesBtn = (Button) findViewById(R.id.saveProfileChangesBtn); 
      mSaveChangesBtn.setEnabled(false); 

      final Button mNextBtn = (Button) findViewById(R.id.NextBtn); 
      mNextBtn.setOnClickListener(new View.OnClickListener() { 
       @Override 
       public void onClick(View v) { 
        Intent intentNext = new Intent(MainActivity.this, SecondActivity.class); 
        startActivity(intentNext); 
       } 
      }); 


      //Change profile image 
      //set onlClick to TextView 
      mChangeProfilePic.setOnClickListener(new View.OnClickListener() { 
       @Override 
       public void onClick(View v) { 
        Toast.makeText(getApplicationContext(), "Change Pic Pressed", Toast.LENGTH_SHORT).show(); 

        //show dialog 
        AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); 
        builder.setTitle("Upload or Take a photo"); 
        builder.setPositiveButton("Upload", new DialogInterface.OnClickListener() { 
         @Override 
         public void onClick(DialogInterface dialog, int which) { 
          //upload image 
          Intent choosePictureIntent = new Intent(Intent.ACTION_GET_CONTENT); 
          choosePictureIntent.setType("image/*"); 
          startActivityForResult(choosePictureIntent, CHOOSE_PIC_REQUEST_CODE); 

          mSaveChangesBtn.setEnabled(true); 

         } 
        }); 
        builder.setNegativeButton("Take Photo", new DialogInterface.OnClickListener() { 
         @Override 
         public void onClick(DialogInterface dialog, int which) { 
          //take photo 
          Intent takePicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 
          mMediaUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE); 
          if (mMediaUri == null) { 
           //display error 
           Toast.makeText(getApplicationContext(), "Sorry there was an error! Try again.", Toast.LENGTH_LONG).show(); 

           mSaveChangesBtn.setEnabled(false); 

          } else { 
           takePicture.putExtra(MediaStore.EXTRA_OUTPUT, mMediaUri); 
           startActivityForResult(takePicture, TAKE_PIC_REQUEST_CODE); 

           mSaveChangesBtn.setEnabled(true); 
          } 
         } 
        }); 
        AlertDialog dialog = builder.create(); 
        dialog.show(); 
       } 
      });//End change profile image onClick Listener 


      //Save profile changes button 
      //Also uploads content to parse and pulls it back same time 
      mSaveChangesBtn.setOnClickListener(new View.OnClickListener() { 
       @Override 
       public void onClick(View v) { 

        //create parse object for image to upload 
        final ParseObject imageUpload = new ParseObject("ImageUploads"); 
        try { 
         //convert image to bytes for upload. 
         byte[] fileBytes = FileHelper.getByteArrayFromFile(MainActivity.this, mMediaUri); 
         if (fileBytes == null) { 
          //there was an error 
          Toast.makeText(getApplicationContext(), "There was an error. Try again!", Toast.LENGTH_LONG).show(); 

          mSaveChangesBtn.setEnabled(false); 
         } else { 

          fileBytes = FileHelper.reduceImageForUpload(fileBytes); 
          String fileName = FileHelper.getFileName(MainActivity.this, mMediaUri, "image"); 
          final ParseFile file = new ParseFile(fileName, fileBytes); 
          imageUpload.saveEventually(new SaveCallback() { 
           @Override 
           public void done(ParseException e) { 
            if (e == null) { 

             imageUpload.put("imageContent", file); 
             imageUpload.saveInBackground(new SaveCallback() { 
                     @Override 
                     public void done(ParseException e) { 
                      Toast.makeText(getApplicationContext(), "Success Uploading iMage!", Toast.LENGTH_LONG).show(); 

                      //Retrieve the recently saved image from Parse 
                      queryParseProfileImages(imageUpload); 

                      mSaveChangesBtn.setEnabled(false); 
                     } 
                    } 

             ); 
            } else { 
             //there was an error 
             Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show(); 

             mSaveChangesBtn.setEnabled(false); 
            } 
           } 
          }); 

         } 

        } catch (Exception e1) { 
         Toast.makeText(getApplicationContext(), e1.getMessage(), Toast.LENGTH_LONG).show(); 
        } 
       }//End onClick(View v) 

      });//End onClick Listener 


//This method queries for the most recent picture taken 
ParseQuery<ParseObject> imagesQuery = new ParseQuery<>("ImageUploads"); 
      imagesQuery.orderByDescending("createdAt"); 
      imagesQuery.findInBackground(new FindCallback<ParseObject>() { 
       @Override 
       public void done(List<ParseObject> images, ParseException e) { 
        if(e == null){ 

         //for (int i = 0; i < images.size(); i++) { 

          final String imgUrl = images.get(0).getParseFile("imageContent").getUrl(); 


          mProfilePic = (ImageView) findViewById(R.id.profileImage); 
          Picasso.with(MainActivity.this).load(imgUrl).into(mProfilePic); 

         //} 
         //images.pinInBackground(); 

         //profileImageId = profImgObj.getObjectId(); 
         //Log.d(TAG, "The object id is: " + profileImageId); 
        }else{ 
         Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_LONG).show(); 
        } 
       } 
      }); 



     }//End onCreate 


     //Method containing ParseQuery to download/pull back the image that was uploaded to Parse 
     //Inside the Image View 
     private void queryParseProfileImages(final ParseObject imageUploadPassed) { 

      ParseFile userImageRetrievedObj = (ParseFile) imageUploadPassed.get("imageContent"); 
      userImageRetrievedObj.getDataInBackground(new GetDataCallback() { 
       public void done(byte[] data, ParseException e) { 
        if (e == null) { 


         final String imgUrl = imageUploadPassed.getParseFile("imageContent").getUrl(); 


         mProfilePic = (ImageView) findViewById(R.id.profileImage); 
         Picasso.with(MainActivity.this).load(imgUrl).into(mProfilePic); 

         imageUploadPassed.pinInBackground(); 


        } else { 
         // something went wrong 
        } 
       } 
      }); 


     } 


     //inner helper method 
     private Uri getOutputMediaFileUri(int mediaTypeImage) { 

      if (isExternalStorageAvailable()) { 
       //get the URI 
       //get external storage dir 
       File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "UPLOADIMAGES"); 
       //create subdirectore if it does not exist 
       if (!mediaStorageDir.exists()) { 
        //create dir 
        if (!mediaStorageDir.mkdirs()) { 

         return null; 
        } 
       } 
       //create a file name 
       //create file 
       File mediaFile = null; 
       Date now = new Date(); 
       String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(now); 

       String path = mediaStorageDir.getPath() + File.separator; 
       if (mediaTypeImage == MEDIA_TYPE_IMAGE) { 
        mediaFile = new File(path + "IMG_" + timestamp + ".jpg"); 
       } 
       //return file uri 
       Log.d("UPLOADIMAGE", "FILE: " + Uri.fromFile(mediaFile)); 

       return Uri.fromFile(mediaFile); 
      } else { 

       return null; 
      } 

     } 

     //check if external storage is mounted. helper method 
     private boolean isExternalStorageAvailable() { 
      String state = Environment.getExternalStorageState(); 
      if (state.equals(Environment.MEDIA_MOUNTED)) { 
       return true; 
      } else { 
       return false; 
      } 
     } 

     @Override 
     protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
      super.onActivityResult(requestCode, resultCode, data); 
      if (resultCode == RESULT_OK) { 
       if (requestCode == CHOOSE_PIC_REQUEST_CODE) { 
        if (data == null) { 
         Toast.makeText(getApplicationContext(), "Image cannot be null!", Toast.LENGTH_LONG).show(); 
        } else { 
         mMediaUri = data.getData(); 
         //set previews 
         mPreviewImageView.setImageURI(mMediaUri); 

         //Bundle extras = data.getExtras(); 

         //Log.e("URI", mMediaUri.toString()); 

         //Bitmap bmp = (Bitmap) extras.get("data"); 


        } 
       } else { 

        Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); 
        mediaScanIntent.setData(mMediaUri); 
        sendBroadcast(mediaScanIntent); 
        //set previews 

        mPreviewImageView.setImageURI(mMediaUri); 

       } 

      } else if (resultCode != RESULT_CANCELED) { 
       Toast.makeText(getApplicationContext(), "Cancelled!", Toast.LENGTH_LONG).show(); 
      } 
     } 


     @Override 
     public boolean onCreateOptionsMenu(Menu menu) { 
      // Inflate the menu; this adds items to the action bar if it is present. 
      getMenuInflater().inflate(R.menu.menu_main, menu); 
      return true; 
     } 


     @Override 
     public boolean onOptionsItemSelected(MenuItem item) { 
      // Handle action bar item clicks here. The action bar will 
      // automatically handle clicks on the Home/Up button, so long 
      // as you specify a parent activity in AndroidManifest.xml. 
      int id = item.getItemId(); 

      //noinspection SimplifiableIfStatement 
      if (id == R.id.action_settings) { 
       return true; 
      } 

      return super.onOptionsItemSelected(item); 
     } 
    } 

risposta

2

In primo luogo, devo dire che questo è un argomento davvero ben formulato e sarei felice che ogni ragazzo con pochi reputazione chiede così buone domande formulate.

Il problema riscontrato è fondamentalmente un problema con il ciclo di vita dell'Android Activity. Immagino che il problema sia davvero banale: non vedo da nessuna parte nella tua attività onCreate() un luogo in cui recuperi l'immagine da Parse: il tuo metodo di download viene chiamato solo in uno onClickListener.

Così, invece di avere qui, vorrei estrarre a un metodo private, sorta di qualcosa di simile a questo:

Edit:

private void queryImagesFromParse(){ 
     ParseQuery<ParseObject> imagesQuery = new ParseQuery<>("User"); 
     imagesQuery.findInBackground(new FindCallback<ParseObject>() { 
      @Override 
      public void done(List<ParseObject> imagesItems, ParseException e) { 
       if(e == null){ 

        ParseUser userCurrentOfParse = ParseUser.getCurrentUser(); 
        if(userCurrentOfParse != null) { 
         //final String imgUrl = imageUploadPassed.getParseFile("imageContent").getUrl(); 
         final String imgUrl = userCurrentOfParse.getParseFile("userProfilePics").getUrl(); 


         mHomeProfilePic = (ImageView) findViewById(R.id.userHomeProfilePicImageView); 
         Picasso.with(HomeActivity.this).load(imgUrl).into(mHomeProfilePic); 

         //imageUploadPassed.pinInBackground(); 

         // profileImageId = imageUploadPassed.getObjectId(); 
         //Log.d(TAG, "The object id is: " + profileImageId); 
        } 

       }else{ 
        Toast.makeText(HomeActivity.this, e.getMessage(), Toast.LENGTH_LONG).show(); 
       } 
      } 
     }); 
    } 

(Il codice di cui sopra è solo per dare un idea approssimativa, sarei sorpreso se compila).

E quindi, si chiama questo metodo alla fine del onCreate() (onStart potrebbe funzionare anche, ma preferirei onCreate()). Naturalmente, è possibile chiamare questo metodo anche dal luogo in cui si trovava prima (che in realtà è quello che succede se si letteralmente extract il metodo Right-Click>Refractor>Extract Method)

Btw, molto buone che si utilizza Picasso ma potrebbe essere meglio per inizializzare con il Context del vostro Activity così Picasso.with(MainActivity.this).load(imgUrl).into(mProfilePic); invece di Picasso.with(getApplicationContext()).load(imgUrl).into(mProfilePic); (dovrebbe essere 1 ns più veloce!)

Edit: anche essere sicuri che l'immagine viene upload e interrogato dalla tabella utente su Parse questa volontà assicurati che ogni utente vedrà la propria immagine (al momento l'utente ha effettuato l'accesso im età) e non quella di ogni altro utente che carica l'immagine successiva.

Spero che aiuti!

+1

Grazie mille per la vostra risposta e per il vostro complimento, ho pensato che sarei rimasta bloccata con questa domanda senza alcun aiuto, quindi il vostro aiuto è molto apprezzato. Quando torno a casa proverò con il tuo approccio e se dovessi incontrare altri problemi ti farò sapere. – Equivocal

+0

Ho apportato modifiche al codice e non funziona ancora. Potrei non aver fatto ciò che hai detto correttamente, ma non ne sono sicuro. Quello che ho fatto è stato creare un metodo al di fuori di onCreate e inserire il contenuto della query all'interno di quel metodo piuttosto che chiamare quel metodo all'interno di onClick all'interno di onCreate. – Equivocal

+0

Sì, perfetto ma hai dimenticato di chiamarlo anche in "onCreate", vero? Devi chiamarlo anche in 'onCreate' per farlo caricare la prima volta. –