私は自分のアプリ内でプロフィール写真の変更を実装する方法の例を見つけるために高低を検索してきました。 Parse.comを使用してプロフィール画像を追加/変更できるようにしたい(今日のすべてのソーシャルメディアアプリと同様)。
例:Twitter、Facebook、Instagramなど、すべてプロファイル画像を取得/アップロードでき、その画像は保存されて表示できます後で。
私はそのようなことを行う方法をカバーする資料を見つけることができず、私がここで達成しようとしていることを理解している人は他にいないようです:
解析からダウンロードした画像は、アプリを終了して再度開いた後も画面に表示されたままですか?
これまでのところ、私のアプリでは、ユーザーはカメラインテントで写真を撮ったり、ギャラリーから画像をアップロードしたりでき、その画像は画像ビューに完全に表示されます。
問題は次のとおりです:アプリを終了して再度開くと、画像ビュー内の画像が表示されなくなります(消えます)。
どうすればこの問題を解決できますか?
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);
}
}
まず、これは非常によく定式化された質問であると言わなければなりません。評判の低いすべての人が非常によく定式化された質問をすることを嬉しく思います。
発生する問題は基本的にAndroidアクティビティライフサイクルの問題です。問題は非常に些細なことだと思います。アクティビティonCreate()
のどこにも画像を取得する場所がありません。解析から:ダウンロードメソッドは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
> Refractor
> Extract Method
の場合に実際に発生することです)
ところで、Picasso
を使用するのは非常に良いですが、Context
のActivity
で初期化する方がよいので、Picasso.with(MainActivity.this).load(imgUrl).into(mProfilePic);
ではなくPicasso.with(getApplicationContext()).load(imgUrl).into(mProfilePic);
を使用します。 (1 ns速くなるはずです!)
編集:また、画像がアップロードされ、ParseのUserテーブルからクエリされていることを確認してください。これにより、各ユーザーには、他のすべての画像ではなく、自分の画像(現在ログインしているユーザーの画像)が表示されます。次の画像をアップロードするユーザー。
それが役に立てば幸い!