如何创建允许上传/更改个人资料图片的应用程序? [英] How To Create An App That Allows For Profile Picture Upload/Change?

查看:20
本文介绍了如何创建允许上传/更改个人资料图片的应用程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在上下搜索,以找到如何在我的应用中实现个人资料图片更改的示例.我希望允许人们使用 Parse.com 添加/更改他们的个人资料图片(类似于今天的所有社交媒体应用).

I have been searching high and low to find an example of how to implement profile picture changes within my app. I want to allow persons to add/change their profile image using Parse.com (Similar to all social media apps today).

例如:Twitter、Facebook、Instagram 等,它们都允许您拍摄/上传个人资料图片,并且该图片会被保存,以便日后查看.

For example: Twitter, Facebook, Instagram and so on, they all allow you to take/upload a profile image and that image is saved and can be viewed later on.

我没有找到任何涵盖如何做这样的事情的材料,而且似乎没有其他人理解我在这里想要实现的目标:

I have had no luck finding any material that covers how to do such a thing and no else seems to be understanding what I'm trying to achieve here:

从 Parse 下载的图像即使在您退出并重新打开应用程序后仍保留在屏幕上?

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

So far in my app the user can take a picture with the camera intent or upload an image from gallery and that image is displayed in an Image View perfectly.

问题是:当我退出并重新打开应用程序时,图像视图中的图像不再显示(消失了).

The problem is: when I exit and re-open the app the image inside of the Image View is no longer displayed (it is gone).

我该如何解决这个问题?

How can I solve this problem?

主要活动:

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

推荐答案

首先,我不得不说这是一个非常明确的问题,我很高兴每个名气不大的人都提出这么好的问题.

First, I have to say that this a really well formulated question and I would be happy that every guy with few reputation asks so good formulated questions.

您遇到的问题基本上是Android Activity生命周期的问题.我想,这个问题真的很微不足道:我在你的 Activity onCreate() 中没有看到你从 Parse 检索图像的地方:你的下载方法只在 onClickListener 中调用>.

The problem you encounter is basically an issue with the Android Activity lifecycle. I guess, the problem is really trivial: I see nowhere in your Activity onCreate() a place where you retrieve the image from Parse: your download method is only called in a onClickListener.

所以我不会把它放在这里,而是将它提取到一个 private 方法中,就像这样:

So instead of having it here, I would extract it to a private method, kind of something like this:

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

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

(The code above is just to give an rough idea, I would be surprised if it compiles).

然后,您在 onCreate() 的末尾调用此方法(onStart 也可以工作,但我更喜欢 onCreate()).当然,你也可以从它之前所在的地方调用这个方法(实际上,如果你从字面上extract 方法Right-Click > Refractor > 提取方法)

And then, you call this method at the end of the onCreate() (onStart could work as well, but I'd prefer onCreate()). Of course, you can call this method also from the place where it was before (that is actually what happens if you literally extract the method Right-Click > Refractor > Extract Method)

顺便说一句,你使用 Picasso 非常好,但最好用 ActivityContext 初始化它,所以 Picasso.with(MainActivity.this).load(imgUrl).into(mProfilePic); 而不是 Picasso.with(getApplicationContext()).load(imgUrl).into(mProfilePic);>(应该快 1 ns!)

Btw, very good that you use Picasso but it could be better to initialise it with the Context of your Activity so Picasso.with(MainActivity.this).load(imgUrl).into(mProfilePic); instead of Picasso.with(getApplicationContext()).load(imgUrl).into(mProfilePic); (should be 1 ns faster!)

还要确保从 Parse 上的 User 表上传和查询图像,这将确保每个用户都会看到自己的图像(当前登录用户的图像),而不是上传下一张图片的所有其他用户.

Also be sure that the image is being upload and queried from the User table on Parse this will ensure that each user will see their own image(currently logged in user's image) and not that of every other user that uploads the next image.

希望能帮到你!

这篇关于如何创建允许上传/更改个人资料图片的应用程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆