如何创建允许配置文件图片上传/更改的应用程序?

时间:2016-01-02 14:24:44

标签: android image android-activity parse-platform android-camera

我一直在寻找一个如何在我的应用中实现个人资料图片更改的示例。我想允许人们使用Parse.com添加/更改他们的个人资料图片(类似于今天的所有社交媒体应用)。

例如: Twitter,Facebook,Instagram等等,它们都允许您拍摄/上传个人资料图片,并保存该图片,以后可以查看。

我没有找到任何材料来解决如何做这样的事情,似乎没有其他任何事情可以理解我在这里想要实现的目标:

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

到目前为止,在我的应用程序中,用户可以使用相机意图拍摄照片或从图库上传图像,该图像将在图像视图中完美显示。

问题是:当我退出并重新打开应用时,图片视图中的图片不再显示(它已消失)。

我该如何解决这个问题?

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);
        }
    }

1 个答案:

答案 0 :(得分:4)

首先,我必须说这是一个非常好的问题,我很高兴每个名声不好的人都会提出如此好的问题。

您遇到的问题基本上是Android Activity生命周期的问题。我猜,问题非常简单:我在您的活动onCreate()中看不到从Parse检索图像的地方:您的下载方法仅在onClickListener中调用。

所以我没有把它提到这里,而是将它提取到private方法,类似这样的东西:

修改

   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();
                }
            }
        });
    }

(上面的代码只是为了给出一个粗略的想法,如果它编译我会感到惊讶。)

然后,您在onCreate()结束时调用此方法(onStart也可以正常工作,但我更喜欢onCreate())。当然,你也可以从之前的地方调用这个方法(实际上,如果你真的extract方法Right-Click&gt; Refractor&gt; {{1} })

顺便说一下,您使用Extract Method非常好,但最好使用Picasso的{​​{1}}对其进行初始化,以便Context代替Activity (应该快1 ns!)

编辑:还要确保图片正在Parse上的User表上传和查询,这样可以确保每个用户都能看到自己的图像(当前登录用户的图像)而不是每个上传下一张图像的其他用户。

希望它有所帮助!