Back4App 和 android studio,如何正确保存 ParseObject 错误
Back4App and android studio , How to properly save a ParseObject Error
这是我 运行 遇到的错误,由于我对 back4app 和 android studio 的理解非常有限(com.parse.ParseException:java.lang.IllegalStateException:无法对未保存的 ParseFile 进行编码。)。
我尝试过的一些解决方案是不可行的,而且似乎是 ParseFile 没有正确保存。我已经尝试了回调函数和进度函数,但似乎没有用。所以在这一点上我不知道如何解决这个问题
这是我撰写片段的代码
package com.example.rentahome.fragments;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageDecoder;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.text.SpannableStringBuilder;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.FileProvider;
import androidx.fragment.app.Fragment;
import com.example.rentahome.ImageFilePath;
import com.example.rentahome.Post;
import com.example.rentahome.R;
import com.example.rentahome.Reviews;
import com.example.rentahome.databinding.FragmentComposeBinding;
import com.parse.Parse;
import com.parse.ParseException;
import com.parse.ParseFile;
import com.parse.ParseObject;
import com.parse.ParseRelation;
import com.parse.ParseUser;
import com.parse.ProgressCallback;
import com.parse.SaveCallback;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import static android.app.Activity.RESULT_OK;
import static com.parse.Parse.getApplicationContext;
public class ComposeFragment extends Fragment {
public static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 43;
public static final int PICK_PHOTO_CODE = 21;
private File photoFile;
FragmentComposeBinding fragmentComposeBinding;
private String photoFileName = "photo.jpg";
public String realPath = new String();
public static final String TAG = "ComposeFragment";
public ComposeFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_compose, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
fragmentComposeBinding = FragmentComposeBinding.bind(view);
fragmentComposeBinding.btnPicture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
uploadImage();
}
});
fragmentComposeBinding.btnSubmit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String address = fragmentComposeBinding.etAddress.getText().toString();
String price = fragmentComposeBinding.etPrice.getText().toString();
String description = fragmentComposeBinding.etDescription.getText().toString();
if(address.isEmpty()){
Toast.makeText(getContext(), "Address cannot be empty", Toast.LENGTH_SHORT).show();
return;
}
if(price.isEmpty()){
Toast.makeText(getContext(), "Price cannot be empty", Toast.LENGTH_SHORT).show();
return;
}
if(description.isEmpty()){
Toast.makeText(getContext(), "Description cannot be empty", Toast.LENGTH_SHORT).show();
return;
}
if(realPath == null || fragmentComposeBinding.ivPostImage.getDrawable()==null){
Toast.makeText(getContext(),"There is no image", Toast.LENGTH_SHORT).show();
return;
}
ParseUser currentUser = ParseUser.getCurrentUser();
savePost(address, price, description, currentUser);
}
});
}
private void uploadImage() {
// create Intent to upload a picture and return control to the calling application
// Edit action for MediaStore
Intent intent = new Intent(Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
// Create a File reference for future access
//photoFile = getPhotoFileUri(photoFileName);
// wrap File object into a content provider
// required for API >= 24
// See https://guides.codepath.com/android/Sharing-Content-with-Intents#sharing-files-with-api-24-or-higher
//Uri fileProvider = FileProvider.getUriForFile(getContext(), "com.example.rentahome.fileprovider", photoFile);
//intent.putExtra(MediaStore.EXTRA_OUTPUT, fileProvider);
// If you call startActivityForResult() using an intent that no app can handle, your app will crash.
// So as long as the result is not null, it's safe to use the intent.
if (intent.resolveActivity(getContext().getPackageManager()) != null) {
// Start the image pick intent to pick photo from external folder
startActivityForResult(intent, PICK_PHOTO_CODE);
}
}
public Bitmap loadFromUri(Uri photoUri) {
Bitmap image = null;
try {
// check version of Anrdoid on device
if(Build.VERSION.SDK_INT > 27) {
// newer version
ImageDecoder.Source source = ImageDecoder.createSource(this.getContext().getContentResolver(), photoUri);
image = ImageDecoder.decodeBitmap(source);
} else {
//support older
image = MediaStore.Images.Media.getBitmap(this.getContext().getContentResolver(),photoUri);
}
} catch (IOException e) {
e.printStackTrace();
}
return image;
}
private File getPhotoFileUri(String fileName) {
// Get safe storage directory for photos
// Use `getExternalFilesDir` on Context to access package-specific directories.
// This way, we don't need to request external read/write runtime permissions.
File mediaStorageDir = new File(getContext().getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), TAG);
// Create the storage directory if it does not exist
if (!mediaStorageDir.exists() && !mediaStorageDir.mkdirs()){
Log.d(TAG, "failed to create directory..");
}
// Return the file target for the photo based on filename
File file = new File(mediaStorageDir.getPath() + File.separator + fileName);
return file;
}
@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_PHOTO_CODE && resultCode == RESULT_OK && data != null && data.getData() != null) {
Uri uri = data.getData();
realPath = ImageFilePath.getPath(getContext(), data.getData());
// realPath = RealPathUtil.getRealPathFromURI_API19(this, data.getData());
Log.i(TAG, "onActivityResult: file path : " + realPath);
Log.i(TAG, "onActivityResult: file path : " + getContext().getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).getPath() );
try {
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContext().getContentResolver(), uri);
// Log.d(TAG, String.valueOf(bitmap));
fragmentComposeBinding.ivPostImage.setImageBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
} else {
Toast.makeText(getContext(), "Something Went Wrong", Toast.LENGTH_SHORT).show();
}
// if ((data != null) && requestCode == PICK_PHOTO_CODE) {
// if (resultCode == RESULT_OK) {
// Uri photoUri = data.getData();
// // by this point we have the camera photo on disk
// //Bitmap selectedImage = BitmapFactory.decodeFile(photoFile.getAbsolutePath());
// //Load the image located at photoUri into selectedImage
// Bitmap selectedImage = loadFromUri(photoUri);
// // RESIZE BITMAP, see section below
// // Load the taken image into a preview
// fragmentComposeBinding.ivPostImage.setImageBitmap(selectedImage);
//
// } else { // Result was a failure
// Toast.makeText(getContext(), "Image not found", Toast.LENGTH_SHORT).show();
// }
// }
}
private void savePost(String address, String price, String description, ParseUser currentUser) {
//Post post = new Post();
ParseObject post = ParseObject.create("Post");
File file = new File(realPath);
ParseFile photo = new ParseFile(file);
photo.saveInBackground();
// post.setImage(photo);
// int parsed_price = Integer.parseInt(price);
// post.setPrice(parsed_price);
// post.setDescription(description);
// post.setUser(currentUser);
// post.setAddress(address);
// //photo.saveInBackground();
ParseRelation<ParseObject> hi;
//parse String price to int..
post.put("image",photo);
post.put("description",description);
post.put("address",address);
post.put("user",currentUser);
post.put("price",price);
//post.put("Reviews",hi);
// Reviews gameScore = new Reviews();
//
// gameScore.setlikesCount(0);
// gameScore.setdislikesCount(0);
// gameScore.setAuthor(currentUser);
// gameScore.setRating((float) (5.0));
// gameScore.setDescription("hi");
////
//// gameScore.put("Description","Hi ");
//// gameScore.put("author",currentUser);
//// gameScore.put("rating",(float)(5.0));
//// gameScore.put("likesCount",0);
//// gameScore.put("dislikesCount",0);
//
// ParseRelation<Reviews> temp = new ParseRelation<Reviews>();
// temp.add(gameScore);
post.saveInBackground(new SaveCallback() {
@Override
public void done(com.parse.ParseException e) {
if(e!=null){
Log.e(TAG,"Issue with saving posts..", e);
Toast.makeText(getContext(), "Error while saving", Toast.LENGTH_SHORT).show();
return;
}
Log.i(TAG,"Saved successfully!");
fragmentComposeBinding.etDescription.setText("");
fragmentComposeBinding.ivPostImage.setImageResource(0);
}
});
}
}
这是我的 post class,它的特别之处之一是我在 post class 中的关系。有一个包含对象 reviews
的 reviews 关系
package com.example.rentahome;
import com.parse.ParseClassName;
import com.parse.ParseFile;
import com.parse.ParseObject;
import com.parse.ParseRelation;
import com.parse.ParseUser;
import java.util.ArrayList;
@ParseClassName("Post")
public class Post extends ParseObject {
public static final String KEY_DESCRIPTION = "description";
public static final String KEY_IMAGE = "image"; //image should be 'uploaded'
public static final String KEY_USER = "user";
public static final String KEY_CREATED_KEY = "createdAt"; //have to figure out how to implement
public static final String KEY_address = "address";
public static final String KEY_price = "price";
public static final String KEY_reviews = "Reviews";
public static final String KEY_objectID = "objectID";
public String getDescription(){
return getString(KEY_DESCRIPTION);
}
public void setDescription(String description){
put(KEY_DESCRIPTION, description);
}
public ParseFile getImage(){
return getParseFile(KEY_IMAGE);
}
public void setImage(ParseFile parseFile){
put(KEY_IMAGE, parseFile);
}
public ParseUser getUser(){
return getParseUser(KEY_USER);
}
public void setUser(ParseUser user){put(KEY_USER, user);}
public String getAddress() {return getString(KEY_address);}
public void setAddress(String address){ put(KEY_address, address);}
public int getPrice(){return getInt(KEY_price);}
public void setPrice(int price){put(KEY_price,price);}
public String getobjectID(){return getString(KEY_objectID);}
public ParseRelation<ParseObject> getrelation() {return getRelation(KEY_reviews);}
public void setrelation(ParseRelation<ParseObject> relation){put(KEY_reviews, relation);}
//public ParseRelation<ParseObject> getReviews(){return getRelation(KEY_reviews);}
//public void setReviews(ParseRelation<ParseObject> reviews){put(KEY_reviews, reviews);}
//public Date getCreatedAt() { return getDate(KEY_CREATED_KEY);}
我的评论class
package com.example.rentahome;
import com.parse.ParseClassName;
import com.parse.ParseObject;
import com.parse.ParseUser;
@ParseClassName("Reviews")
public class Reviews extends ParseObject {
public static final String KEY_author = "author";
public static final String KEY_description = "Description";
public static final String KEY_likesCount = "likesCount";
public static final String KEY_dislikesCount = "dislikesCount";
public static final String KEY_rating = "rating";
public String getDescription(){return getString(KEY_description);}
public void setDescription(String description){put(KEY_description, description);}
public ParseUser getAuthor(){return getParseUser(KEY_author); }
public void setAuthor(ParseUser author){put(KEY_author,author);}
public float getRating(){return (float)getDouble(KEY_rating);}
public void setRating(float rating) {put(KEY_rating, rating);}
public int getlikesCount() {return getInt(KEY_likesCount);}
public void setlikesCount(int likesCount){put(KEY_likesCount, likesCount);}
public int getdislikesCount() {return getInt(KEY_dislikesCount);}
public void setdislikesCount(int dislikesCount){put(KEY_dislikesCount, dislikesCount);}
}
这是错误信息
E/ComposeFragment: Issue with saving posts..
com.parse.ParseException: java.lang.IllegalStateException: Unable to encode an unsaved ParseFile.
at com.parse.ParseTaskUtils.run(ParseTaskUtils.java:119)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Caused by: java.lang.IllegalStateException: Unable to encode an unsaved ParseFile.
at com.parse.ParseFile.encode(ParseFile.java:653)
at com.parse.ParseEncoder.encode(ParseEncoder.java:77)
at com.parse.ParseSetOperation.encode(ParseSetOperation.java:31)
at com.parse.ParseEncoder.encode(ParseEncoder.java:126)
at com.parse.ParseObjectCoder.encode(ParseObjectCoder.java:57)
at com.parse.NetworkObjectController.saveAsync(NetworkObjectController.java:60)
at com.parse.ParseObject.then(ParseObject.java:2282)
at com.parse.ParseObject.then(ParseObject.java:2277)
at com.parse.boltsinternal.Task.run(Task.java:907)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeAfterTask(Task.java:898)
at com.parse.boltsinternal.Task.continueWithTask(Task.java:713)
at com.parse.boltsinternal.Task.continueWithTask(Task.java:724)
at com.parse.boltsinternal.Task.then(Task.java:816)
at com.parse.boltsinternal.Task.then(Task.java:804)
at com.parse.boltsinternal.Task.run(Task.java:907)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeAfterTask(Task.java:898)
at com.parse.boltsinternal.Task.access0(Task.java:28)
at com.parse.boltsinternal.Task.then(Task.java:706)
at com.parse.boltsinternal.Task.then(Task.java:703)
at com.parse.boltsinternal.Task.runContinuations(Task.java:946)
at com.parse.boltsinternal.Task.trySetResult(Task.java:984)
at com.parse.boltsinternal.TaskCompletionSource.trySetResult(TaskCompletionSource.java:45)
at com.parse.boltsinternal.TaskCompletionSource.setResult(TaskCompletionSource.java:68)
at com.parse.boltsinternal.Task.then(Task.java:924)
at com.parse.boltsinternal.Task.then(Task.java:911)
at com.parse.boltsinternal.Task.run(Task.java:866)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeImmediately(Task.java:857)
at com.parse.boltsinternal.Task.continueWith(Task.java:659)
at com.parse.boltsinternal.Task.continueWith(Task.java:670)
at com.parse.boltsinternal.Task.run(Task.java:911)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeAfterTask(Task.java:898)
at com.parse.boltsinternal.Task.access0(Task.java:28)
at com.parse.boltsinternal.Task.then(Task.java:706)
at com.parse.boltsinternal.Task.then(Task.java:703)
at com.parse.boltsinternal.Task.runContinuations(Task.java:946)
at com.parse.boltsinternal.Task.trySetResult(Task.java:984)
at com.parse.boltsinternal.TaskCompletionSource.trySetResult(TaskCompletionSource.java:45)
at com.parse.boltsinternal.TaskCompletionSource.setResult(TaskCompletionSource.java:68)
at com.parse.boltsinternal.Task.then(Task.java:562)
at com.parse.boltsinternal.Task.then(Task.java:536)
at com.parse.boltsinternal.Task.run(Task.java:866)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeImmediately(Task.java:857)
at com.parse.boltsinternal.Task.access[=14=]0(Task.java:28)
at com.parse.boltsinternal.Task.then(Task.java:652)
at com.parse.boltsinternal.Task.then(Task.java:649)
E/ComposeFragment: at com.parse.boltsinternal.Task.runContinuations(Task.java:946)
at com.parse.boltsinternal.Task.trySetResult(Task.java:984)
at com.parse.boltsinternal.TaskCompletionSource.trySetResult(TaskCompletionSource.java:45)
at com.parse.boltsinternal.TaskCompletionSource.setResult(TaskCompletionSource.java:68)
at com.parse.boltsinternal.Task.run(Task.java:867)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeImmediately(Task.java:857)
at com.parse.boltsinternal.Task.access[=14=]0(Task.java:28)
at com.parse.boltsinternal.Task.then(Task.java:652)
at com.parse.boltsinternal.Task.then(Task.java:649)
at com.parse.boltsinternal.Task.runContinuations(Task.java:946)
at com.parse.boltsinternal.Task.trySetError(Task.java:1001)
at com.parse.boltsinternal.TaskCompletionSource.trySetError(TaskCompletionSource.java:52)
at com.parse.boltsinternal.TaskCompletionSource.setError(TaskCompletionSource.java:77)
at com.parse.boltsinternal.Task.then(Task.java:552)
at com.parse.boltsinternal.Task.then(Task.java:536)
at com.parse.boltsinternal.Task.run(Task.java:866)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeImmediately(Task.java:857)
at com.parse.boltsinternal.Task.access[=14=]0(Task.java:28)
at com.parse.boltsinternal.Task.then(Task.java:652)
at com.parse.boltsinternal.Task.then(Task.java:649)
at com.parse.boltsinternal.Task.runContinuations(Task.java:946)
at com.parse.boltsinternal.Task.trySetError(Task.java:1001)
at com.parse.boltsinternal.TaskCompletionSource.trySetError(TaskCompletionSource.java:52)
at com.parse.boltsinternal.TaskCompletionSource.setError(TaskCompletionSource.java:77)
at com.parse.boltsinternal.Task.then(Task.java:922)
at com.parse.boltsinternal.Task.then(Task.java:911)
at com.parse.boltsinternal.Task.run(Task.java:866)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeImmediately(Task.java:857)
at com.parse.boltsinternal.Task.access[=14=]0(Task.java:28)
at com.parse.boltsinternal.Task.then(Task.java:652)
at com.parse.boltsinternal.Task.then(Task.java:649)
at com.parse.boltsinternal.Task.runContinuations(Task.java:946)
at com.parse.boltsinternal.Task.trySetError(Task.java:1001)
at com.parse.boltsinternal.TaskCompletionSource.trySetError(TaskCompletionSource.java:52)
at com.parse.boltsinternal.TaskCompletionSource.setError(TaskCompletionSource.java:77)
at com.parse.boltsinternal.Task.then(Task.java:922)
at com.parse.boltsinternal.Task.then(Task.java:911)
at com.parse.boltsinternal.Task.run(Task.java:866)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeImmediately(Task.java:857)
at com.parse.boltsinternal.Task.continueWith(Task.java:659)
at com.parse.boltsinternal.Task.continueWith(Task.java:670)
at com.parse.boltsinternal.Task.run(Task.java:911)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeAfterTask(Task.java:898)
at com.parse.boltsinternal.Task.access0(Task.java:28)
at com.parse.boltsinternal.Task.then(Task.java:706)
at com.parse.boltsinternal.Task.then(Task.java:703)
at com.parse.boltsinternal.Task.runContinuations(Task.java:946)
at com.parse.boltsinternal.Task.trySetError(Task.java:1001)
at com.parse.boltsinternal.TaskCompletionSource.trySetError(TaskCompletionSource.java:52)
at com.parse.boltsinternal.TaskCompletionSource.setError(TaskCompletionSource.java:77)
at com.parse.boltsinternal.Task.then(Task.java:922)
at com.parse.boltsinternal.Task.then(Task.java:911)
at com.parse.boltsinternal.Task.run(Task.java:866)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeImmediately(Task.java:857)
at com.parse.boltsinternal.Task.continueWith(Task.java:659)
at com.parse.boltsinternal.Task.continueWith(Task.java:670)
at com.parse.boltsinternal.Task.run(Task.java:911)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:923)
出现问题是因为您没有等待 photo.saveInBackground
完成。您的代码应如下所示:
ParseObject post = ParseObject.create("Post");
File file = new File(realPath);
ParseFile photo = new ParseFile(file);
photo.saveInBackground(new SaveCallback() {
@Override
public void done(com.parse.ParseException e) {
// Handle success or failure here ...
post.put("image",photo);
post.put("description",description);
post.put("address",address);
post.put("user",currentUser);
post.put("price",price);
post.saveInBackground(new SaveCallback() {
@Override
public void done(com.parse.ParseException e) {
// Handle success or failure here ...
}
});
}
});
这是我 运行 遇到的错误,由于我对 back4app 和 android studio 的理解非常有限(com.parse.ParseException:java.lang.IllegalStateException:无法对未保存的 ParseFile 进行编码。)。 我尝试过的一些解决方案是不可行的,而且似乎是 ParseFile 没有正确保存。我已经尝试了回调函数和进度函数,但似乎没有用。所以在这一点上我不知道如何解决这个问题 这是我撰写片段的代码
package com.example.rentahome.fragments;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageDecoder;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.text.SpannableStringBuilder;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.FileProvider;
import androidx.fragment.app.Fragment;
import com.example.rentahome.ImageFilePath;
import com.example.rentahome.Post;
import com.example.rentahome.R;
import com.example.rentahome.Reviews;
import com.example.rentahome.databinding.FragmentComposeBinding;
import com.parse.Parse;
import com.parse.ParseException;
import com.parse.ParseFile;
import com.parse.ParseObject;
import com.parse.ParseRelation;
import com.parse.ParseUser;
import com.parse.ProgressCallback;
import com.parse.SaveCallback;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import static android.app.Activity.RESULT_OK;
import static com.parse.Parse.getApplicationContext;
public class ComposeFragment extends Fragment {
public static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 43;
public static final int PICK_PHOTO_CODE = 21;
private File photoFile;
FragmentComposeBinding fragmentComposeBinding;
private String photoFileName = "photo.jpg";
public String realPath = new String();
public static final String TAG = "ComposeFragment";
public ComposeFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_compose, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
fragmentComposeBinding = FragmentComposeBinding.bind(view);
fragmentComposeBinding.btnPicture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
uploadImage();
}
});
fragmentComposeBinding.btnSubmit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String address = fragmentComposeBinding.etAddress.getText().toString();
String price = fragmentComposeBinding.etPrice.getText().toString();
String description = fragmentComposeBinding.etDescription.getText().toString();
if(address.isEmpty()){
Toast.makeText(getContext(), "Address cannot be empty", Toast.LENGTH_SHORT).show();
return;
}
if(price.isEmpty()){
Toast.makeText(getContext(), "Price cannot be empty", Toast.LENGTH_SHORT).show();
return;
}
if(description.isEmpty()){
Toast.makeText(getContext(), "Description cannot be empty", Toast.LENGTH_SHORT).show();
return;
}
if(realPath == null || fragmentComposeBinding.ivPostImage.getDrawable()==null){
Toast.makeText(getContext(),"There is no image", Toast.LENGTH_SHORT).show();
return;
}
ParseUser currentUser = ParseUser.getCurrentUser();
savePost(address, price, description, currentUser);
}
});
}
private void uploadImage() {
// create Intent to upload a picture and return control to the calling application
// Edit action for MediaStore
Intent intent = new Intent(Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
// Create a File reference for future access
//photoFile = getPhotoFileUri(photoFileName);
// wrap File object into a content provider
// required for API >= 24
// See https://guides.codepath.com/android/Sharing-Content-with-Intents#sharing-files-with-api-24-or-higher
//Uri fileProvider = FileProvider.getUriForFile(getContext(), "com.example.rentahome.fileprovider", photoFile);
//intent.putExtra(MediaStore.EXTRA_OUTPUT, fileProvider);
// If you call startActivityForResult() using an intent that no app can handle, your app will crash.
// So as long as the result is not null, it's safe to use the intent.
if (intent.resolveActivity(getContext().getPackageManager()) != null) {
// Start the image pick intent to pick photo from external folder
startActivityForResult(intent, PICK_PHOTO_CODE);
}
}
public Bitmap loadFromUri(Uri photoUri) {
Bitmap image = null;
try {
// check version of Anrdoid on device
if(Build.VERSION.SDK_INT > 27) {
// newer version
ImageDecoder.Source source = ImageDecoder.createSource(this.getContext().getContentResolver(), photoUri);
image = ImageDecoder.decodeBitmap(source);
} else {
//support older
image = MediaStore.Images.Media.getBitmap(this.getContext().getContentResolver(),photoUri);
}
} catch (IOException e) {
e.printStackTrace();
}
return image;
}
private File getPhotoFileUri(String fileName) {
// Get safe storage directory for photos
// Use `getExternalFilesDir` on Context to access package-specific directories.
// This way, we don't need to request external read/write runtime permissions.
File mediaStorageDir = new File(getContext().getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), TAG);
// Create the storage directory if it does not exist
if (!mediaStorageDir.exists() && !mediaStorageDir.mkdirs()){
Log.d(TAG, "failed to create directory..");
}
// Return the file target for the photo based on filename
File file = new File(mediaStorageDir.getPath() + File.separator + fileName);
return file;
}
@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_PHOTO_CODE && resultCode == RESULT_OK && data != null && data.getData() != null) {
Uri uri = data.getData();
realPath = ImageFilePath.getPath(getContext(), data.getData());
// realPath = RealPathUtil.getRealPathFromURI_API19(this, data.getData());
Log.i(TAG, "onActivityResult: file path : " + realPath);
Log.i(TAG, "onActivityResult: file path : " + getContext().getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).getPath() );
try {
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContext().getContentResolver(), uri);
// Log.d(TAG, String.valueOf(bitmap));
fragmentComposeBinding.ivPostImage.setImageBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
} else {
Toast.makeText(getContext(), "Something Went Wrong", Toast.LENGTH_SHORT).show();
}
// if ((data != null) && requestCode == PICK_PHOTO_CODE) {
// if (resultCode == RESULT_OK) {
// Uri photoUri = data.getData();
// // by this point we have the camera photo on disk
// //Bitmap selectedImage = BitmapFactory.decodeFile(photoFile.getAbsolutePath());
// //Load the image located at photoUri into selectedImage
// Bitmap selectedImage = loadFromUri(photoUri);
// // RESIZE BITMAP, see section below
// // Load the taken image into a preview
// fragmentComposeBinding.ivPostImage.setImageBitmap(selectedImage);
//
// } else { // Result was a failure
// Toast.makeText(getContext(), "Image not found", Toast.LENGTH_SHORT).show();
// }
// }
}
private void savePost(String address, String price, String description, ParseUser currentUser) {
//Post post = new Post();
ParseObject post = ParseObject.create("Post");
File file = new File(realPath);
ParseFile photo = new ParseFile(file);
photo.saveInBackground();
// post.setImage(photo);
// int parsed_price = Integer.parseInt(price);
// post.setPrice(parsed_price);
// post.setDescription(description);
// post.setUser(currentUser);
// post.setAddress(address);
// //photo.saveInBackground();
ParseRelation<ParseObject> hi;
//parse String price to int..
post.put("image",photo);
post.put("description",description);
post.put("address",address);
post.put("user",currentUser);
post.put("price",price);
//post.put("Reviews",hi);
// Reviews gameScore = new Reviews();
//
// gameScore.setlikesCount(0);
// gameScore.setdislikesCount(0);
// gameScore.setAuthor(currentUser);
// gameScore.setRating((float) (5.0));
// gameScore.setDescription("hi");
////
//// gameScore.put("Description","Hi ");
//// gameScore.put("author",currentUser);
//// gameScore.put("rating",(float)(5.0));
//// gameScore.put("likesCount",0);
//// gameScore.put("dislikesCount",0);
//
// ParseRelation<Reviews> temp = new ParseRelation<Reviews>();
// temp.add(gameScore);
post.saveInBackground(new SaveCallback() {
@Override
public void done(com.parse.ParseException e) {
if(e!=null){
Log.e(TAG,"Issue with saving posts..", e);
Toast.makeText(getContext(), "Error while saving", Toast.LENGTH_SHORT).show();
return;
}
Log.i(TAG,"Saved successfully!");
fragmentComposeBinding.etDescription.setText("");
fragmentComposeBinding.ivPostImage.setImageResource(0);
}
});
}
}
这是我的 post class,它的特别之处之一是我在 post class 中的关系。有一个包含对象 reviews
的 reviews 关系package com.example.rentahome;
import com.parse.ParseClassName;
import com.parse.ParseFile;
import com.parse.ParseObject;
import com.parse.ParseRelation;
import com.parse.ParseUser;
import java.util.ArrayList;
@ParseClassName("Post")
public class Post extends ParseObject {
public static final String KEY_DESCRIPTION = "description";
public static final String KEY_IMAGE = "image"; //image should be 'uploaded'
public static final String KEY_USER = "user";
public static final String KEY_CREATED_KEY = "createdAt"; //have to figure out how to implement
public static final String KEY_address = "address";
public static final String KEY_price = "price";
public static final String KEY_reviews = "Reviews";
public static final String KEY_objectID = "objectID";
public String getDescription(){
return getString(KEY_DESCRIPTION);
}
public void setDescription(String description){
put(KEY_DESCRIPTION, description);
}
public ParseFile getImage(){
return getParseFile(KEY_IMAGE);
}
public void setImage(ParseFile parseFile){
put(KEY_IMAGE, parseFile);
}
public ParseUser getUser(){
return getParseUser(KEY_USER);
}
public void setUser(ParseUser user){put(KEY_USER, user);}
public String getAddress() {return getString(KEY_address);}
public void setAddress(String address){ put(KEY_address, address);}
public int getPrice(){return getInt(KEY_price);}
public void setPrice(int price){put(KEY_price,price);}
public String getobjectID(){return getString(KEY_objectID);}
public ParseRelation<ParseObject> getrelation() {return getRelation(KEY_reviews);}
public void setrelation(ParseRelation<ParseObject> relation){put(KEY_reviews, relation);}
//public ParseRelation<ParseObject> getReviews(){return getRelation(KEY_reviews);}
//public void setReviews(ParseRelation<ParseObject> reviews){put(KEY_reviews, reviews);}
//public Date getCreatedAt() { return getDate(KEY_CREATED_KEY);}
我的评论class
package com.example.rentahome;
import com.parse.ParseClassName;
import com.parse.ParseObject;
import com.parse.ParseUser;
@ParseClassName("Reviews")
public class Reviews extends ParseObject {
public static final String KEY_author = "author";
public static final String KEY_description = "Description";
public static final String KEY_likesCount = "likesCount";
public static final String KEY_dislikesCount = "dislikesCount";
public static final String KEY_rating = "rating";
public String getDescription(){return getString(KEY_description);}
public void setDescription(String description){put(KEY_description, description);}
public ParseUser getAuthor(){return getParseUser(KEY_author); }
public void setAuthor(ParseUser author){put(KEY_author,author);}
public float getRating(){return (float)getDouble(KEY_rating);}
public void setRating(float rating) {put(KEY_rating, rating);}
public int getlikesCount() {return getInt(KEY_likesCount);}
public void setlikesCount(int likesCount){put(KEY_likesCount, likesCount);}
public int getdislikesCount() {return getInt(KEY_dislikesCount);}
public void setdislikesCount(int dislikesCount){put(KEY_dislikesCount, dislikesCount);}
}
这是错误信息
E/ComposeFragment: Issue with saving posts..
com.parse.ParseException: java.lang.IllegalStateException: Unable to encode an unsaved ParseFile.
at com.parse.ParseTaskUtils.run(ParseTaskUtils.java:119)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Caused by: java.lang.IllegalStateException: Unable to encode an unsaved ParseFile.
at com.parse.ParseFile.encode(ParseFile.java:653)
at com.parse.ParseEncoder.encode(ParseEncoder.java:77)
at com.parse.ParseSetOperation.encode(ParseSetOperation.java:31)
at com.parse.ParseEncoder.encode(ParseEncoder.java:126)
at com.parse.ParseObjectCoder.encode(ParseObjectCoder.java:57)
at com.parse.NetworkObjectController.saveAsync(NetworkObjectController.java:60)
at com.parse.ParseObject.then(ParseObject.java:2282)
at com.parse.ParseObject.then(ParseObject.java:2277)
at com.parse.boltsinternal.Task.run(Task.java:907)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeAfterTask(Task.java:898)
at com.parse.boltsinternal.Task.continueWithTask(Task.java:713)
at com.parse.boltsinternal.Task.continueWithTask(Task.java:724)
at com.parse.boltsinternal.Task.then(Task.java:816)
at com.parse.boltsinternal.Task.then(Task.java:804)
at com.parse.boltsinternal.Task.run(Task.java:907)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeAfterTask(Task.java:898)
at com.parse.boltsinternal.Task.access0(Task.java:28)
at com.parse.boltsinternal.Task.then(Task.java:706)
at com.parse.boltsinternal.Task.then(Task.java:703)
at com.parse.boltsinternal.Task.runContinuations(Task.java:946)
at com.parse.boltsinternal.Task.trySetResult(Task.java:984)
at com.parse.boltsinternal.TaskCompletionSource.trySetResult(TaskCompletionSource.java:45)
at com.parse.boltsinternal.TaskCompletionSource.setResult(TaskCompletionSource.java:68)
at com.parse.boltsinternal.Task.then(Task.java:924)
at com.parse.boltsinternal.Task.then(Task.java:911)
at com.parse.boltsinternal.Task.run(Task.java:866)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeImmediately(Task.java:857)
at com.parse.boltsinternal.Task.continueWith(Task.java:659)
at com.parse.boltsinternal.Task.continueWith(Task.java:670)
at com.parse.boltsinternal.Task.run(Task.java:911)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeAfterTask(Task.java:898)
at com.parse.boltsinternal.Task.access0(Task.java:28)
at com.parse.boltsinternal.Task.then(Task.java:706)
at com.parse.boltsinternal.Task.then(Task.java:703)
at com.parse.boltsinternal.Task.runContinuations(Task.java:946)
at com.parse.boltsinternal.Task.trySetResult(Task.java:984)
at com.parse.boltsinternal.TaskCompletionSource.trySetResult(TaskCompletionSource.java:45)
at com.parse.boltsinternal.TaskCompletionSource.setResult(TaskCompletionSource.java:68)
at com.parse.boltsinternal.Task.then(Task.java:562)
at com.parse.boltsinternal.Task.then(Task.java:536)
at com.parse.boltsinternal.Task.run(Task.java:866)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeImmediately(Task.java:857)
at com.parse.boltsinternal.Task.access[=14=]0(Task.java:28)
at com.parse.boltsinternal.Task.then(Task.java:652)
at com.parse.boltsinternal.Task.then(Task.java:649)
E/ComposeFragment: at com.parse.boltsinternal.Task.runContinuations(Task.java:946)
at com.parse.boltsinternal.Task.trySetResult(Task.java:984)
at com.parse.boltsinternal.TaskCompletionSource.trySetResult(TaskCompletionSource.java:45)
at com.parse.boltsinternal.TaskCompletionSource.setResult(TaskCompletionSource.java:68)
at com.parse.boltsinternal.Task.run(Task.java:867)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeImmediately(Task.java:857)
at com.parse.boltsinternal.Task.access[=14=]0(Task.java:28)
at com.parse.boltsinternal.Task.then(Task.java:652)
at com.parse.boltsinternal.Task.then(Task.java:649)
at com.parse.boltsinternal.Task.runContinuations(Task.java:946)
at com.parse.boltsinternal.Task.trySetError(Task.java:1001)
at com.parse.boltsinternal.TaskCompletionSource.trySetError(TaskCompletionSource.java:52)
at com.parse.boltsinternal.TaskCompletionSource.setError(TaskCompletionSource.java:77)
at com.parse.boltsinternal.Task.then(Task.java:552)
at com.parse.boltsinternal.Task.then(Task.java:536)
at com.parse.boltsinternal.Task.run(Task.java:866)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeImmediately(Task.java:857)
at com.parse.boltsinternal.Task.access[=14=]0(Task.java:28)
at com.parse.boltsinternal.Task.then(Task.java:652)
at com.parse.boltsinternal.Task.then(Task.java:649)
at com.parse.boltsinternal.Task.runContinuations(Task.java:946)
at com.parse.boltsinternal.Task.trySetError(Task.java:1001)
at com.parse.boltsinternal.TaskCompletionSource.trySetError(TaskCompletionSource.java:52)
at com.parse.boltsinternal.TaskCompletionSource.setError(TaskCompletionSource.java:77)
at com.parse.boltsinternal.Task.then(Task.java:922)
at com.parse.boltsinternal.Task.then(Task.java:911)
at com.parse.boltsinternal.Task.run(Task.java:866)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeImmediately(Task.java:857)
at com.parse.boltsinternal.Task.access[=14=]0(Task.java:28)
at com.parse.boltsinternal.Task.then(Task.java:652)
at com.parse.boltsinternal.Task.then(Task.java:649)
at com.parse.boltsinternal.Task.runContinuations(Task.java:946)
at com.parse.boltsinternal.Task.trySetError(Task.java:1001)
at com.parse.boltsinternal.TaskCompletionSource.trySetError(TaskCompletionSource.java:52)
at com.parse.boltsinternal.TaskCompletionSource.setError(TaskCompletionSource.java:77)
at com.parse.boltsinternal.Task.then(Task.java:922)
at com.parse.boltsinternal.Task.then(Task.java:911)
at com.parse.boltsinternal.Task.run(Task.java:866)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeImmediately(Task.java:857)
at com.parse.boltsinternal.Task.continueWith(Task.java:659)
at com.parse.boltsinternal.Task.continueWith(Task.java:670)
at com.parse.boltsinternal.Task.run(Task.java:911)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeAfterTask(Task.java:898)
at com.parse.boltsinternal.Task.access0(Task.java:28)
at com.parse.boltsinternal.Task.then(Task.java:706)
at com.parse.boltsinternal.Task.then(Task.java:703)
at com.parse.boltsinternal.Task.runContinuations(Task.java:946)
at com.parse.boltsinternal.Task.trySetError(Task.java:1001)
at com.parse.boltsinternal.TaskCompletionSource.trySetError(TaskCompletionSource.java:52)
at com.parse.boltsinternal.TaskCompletionSource.setError(TaskCompletionSource.java:77)
at com.parse.boltsinternal.Task.then(Task.java:922)
at com.parse.boltsinternal.Task.then(Task.java:911)
at com.parse.boltsinternal.Task.run(Task.java:866)
at com.parse.boltsinternal.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:113)
at com.parse.boltsinternal.Task.completeImmediately(Task.java:857)
at com.parse.boltsinternal.Task.continueWith(Task.java:659)
at com.parse.boltsinternal.Task.continueWith(Task.java:670)
at com.parse.boltsinternal.Task.run(Task.java:911)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:923)
出现问题是因为您没有等待 photo.saveInBackground
完成。您的代码应如下所示:
ParseObject post = ParseObject.create("Post");
File file = new File(realPath);
ParseFile photo = new ParseFile(file);
photo.saveInBackground(new SaveCallback() {
@Override
public void done(com.parse.ParseException e) {
// Handle success or failure here ...
post.put("image",photo);
post.put("description",description);
post.put("address",address);
post.put("user",currentUser);
post.put("price",price);
post.saveInBackground(new SaveCallback() {
@Override
public void done(com.parse.ParseException e) {
// Handle success or failure here ...
}
});
}
});