I am trying to get the image path string from an imageView.
The imageView is charged using a string path store in SQLite db.
When I modify an item of my Db in some fiels other than image path one, I can't read back the path from imageView to correctly update the db. So the field image path become null after any kind of update.
In code, when I click the save button I call the saveProduct() method:
private void saveProduct() {
// Read from input field
//Use trim to eliminate leading or trailing white space
String nameString = mNameEditText.getText().toString().trim();
String qtyString = mQtyEditText.getText().toString().trim();
String priceString = mPriceEditText.getText().toString().trim();
String mailString = mEmailEditText.getText().toString().trim();
String phoneString = mPhoneEditText.getText().toString().trim();
// Check if this is a new product or an existing one
if (mcurrentProdUri == null &&
TextUtils.isEmpty(nameString) && TextUtils.isEmpty(qtyString)
&& TextUtils.isEmpty(priceString)&& TextUtils.isEmpty(mailString)
&& TextUtils.isEmpty(phoneString)) {
return;
}
//Create a ContentValues object to populate the database
ContentValues values = new ContentValues();
values.put(InventoryContract.ProductEntry.COLUMN_PRODUCT_NAME, nameString);
values.put(InventoryContract.ProductEntry.COLUMN_PRODUCT_QTY, qtyString);
values.put(InventoryContract.ProductEntry.COLUMN_PRODUCT_PRICE, priceString);
values.put(InventoryContract.ProductEntry.COLUMN_EMAIL, mailString);
values.put(InventoryContract.ProductEntry.COLUMN_PHONE, phoneString);
values.put(InventoryContract.ProductEntry.COLUMN_PRODUCT_PIC, picPath);
//Determine if this is a new product or not by checking if mCurrentProdUri is null or not
if (mcurrentProdUri == null) {
Uri newUri = getContentResolver().insert(InventoryContract.ProductEntry.CONTENT_URI, values);
// check if newUri is null or not
if (newUri == null){
//Show an error toast message
Toast.makeText(this, "There has been an error inserting a new product", Toast.LENGTH_SHORT).show();
} else {
//Otherwise show a successful addition message
Toast.makeText(this, "A new product has been added!", Toast.LENGTH_SHORT).show();
}
} else {
//Otherwise if this is an existing product proceed updating it with new data
int rowsAffected = getContentResolver().update(mcurrentProdUri, values, null, null);
if (rowsAffected == 0) {
// If no rows were affected show error toast message
Toast.makeText(this, "There has been an error in updating the product", Toast.LENGTH_SHORT).show();
} else {
// Otherwise the update was successful and we can show the related Toast message
Toast.makeText(this, "The product has been updated!", Toast.LENGTH_SHORT).show();
}
}
}
I already read all related posts, but I really don't know how I can make the method read the imageView to get out the related image path (or Uri)
Many thanks for support
You need to keep track of the uri at the activity/fragment level before you load the imageview as it's not the responsibility of a regular ImageView to remember it's source.
You can, however, build an extended ImageView that is responsible for that if it helps your case:
class MyImageView extends ImageView {
private Uri mImageUri;
public MyImageView(Context context) {
super(context);
}
#Override
public void setImageURI(#Nullable Uri uri) {
super.setImageURI(uri);
mImageUri = uri;
}
public Uri getImageUri(){
return mImageUri;
}
}
If you do go that route, you have to take view state saving into consideration during config changes or you may lose that uri.
Related
I'm currently creating an app that needs to download a couple of videos then save the local path of it on a SQLite database.
At first, I wanted to get the URL of the video I downloaded but I can't seem to find anything that discusses about it. I tried to get COLUMN_MEDIAPROVIDER_URI and COLUMN_URI from the intent passed on the BroadcastReceiver for DownloadManager.ACTION_DOWNLOAD_COMPLETE but they return null.
Then I found about EXTRA_DOWNLOAD_ID. But if I use that, I still need to use something like a new HashMap that got the EXTRA_DOWNLOAD_ID of my download and the id of the video on my SQLite database for checking which is which.
I'm fine with that but I want to know if there's an easier way to do the thing I want.
I did this using OkHttp, as follows:
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(YOUR_URL)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
// ERROR MESSAGE
}
#Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
response.body().byteStream(); // byteStream with your result.
}
}
});
Another thing, maybe would be better if you store the videos on memory and just the address in your SQLite.
Using the code below from the SO question here
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
// get the DownloadManager instance
DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Query q = new DownloadManager.Query();
Cursor c = manager.query(q);
if(c.moveToFirst()) {
do {
String name = c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME));
Log.i("DOWNLOAD LISTENER", "file name: " + name);
} while (c.moveToNext());
} else {
Log.i("DOWNLOAD LISTENER", "empty cursor :(");
}
c.close();
}
}
and saving the download id on my ArrayList I was able to make a simpler way to check which download is finished.
I modified it to look like this for my use case.
Cursor c = dlMgr.query(new DownloadManager.Query());
boolean found = false;
if(c.moveToFirst()) {
do {
String dlFilePath = c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME));
int dlId = Integer.parseInt( c.getString(c.getColumnIndex(DownloadManager.COLUMN_ID)) );
for(int x = 0; x < vidArrLst.size(); x++){
VideoAd va = vidArrLst.get(x);
if(va.getDownloadId() == dlId){
dbHelper.updateLocalPath(va.getVideoId(), dlFilePath);
va.setLocalPath(dlFilePath);
found = true;
break;
}
}
} while (c.moveToNext() && !found);
} else {
Log.d(TAG, "empty cursor :(");
}
UPDATE:
Sometimes this method will show that 2 downloads finished with the same file name which results to a video item to not have a local path. What I did is check if the local path is empty, download id is greater than 0, and if the download id is still downloading before playing a video so I can redownload a video and fix the gap and play the local file the next time the video needs to be played.
The situation is as following:
I send a login request using the method showLoginUI and then, after selecting a provider (Twitter, g+, etc.) the app goes to the onError callback of my GSLoginUIListener with the error "Account pending registration". Until that point, everything is fine. The problem is when I try to create another GSRequest with the method "accounts.setAccountInfo" like in the following code:
GSRequest setAccountInfoRequest = new GSRequest(getString(R.string.gigya_api_key),"accounts.setAccountInfo");
As parameter, I believe I have to add the regToken but where can I get it? In the iOS SDK, there is an Error object (that you get from the GSResponse that allows you to get it like this:
token = error.userInfo["regToken"]
But there is nothing like that on the Android SDK, from the GSResponse I just can get the error code, error message and error details. So, in short, how can I get the regToken that I need for my request? In the documentation does not go into the details of the actual implementation and I have not seen any examples.
Unlike the iOS and .NET SDKs, the Android SDK does not have a publicly expose or documented GSRequest class, so invoking a request the way you are doing it is not advisable.
Instead, you should use GSAPI.sendRequest with a GSResponseListener. The GSResponseListener will have a response object with the method getData which can be invoked to get a dictionary object of all the parameters returned from the request.
An example of how this can be done is provided in our Gigya CS Android demo hosted on GitHub and can be examined in the file SessionInfoFragment.java#121-191.
public void refreshView() {
GSAPI gigya = GSAPI.getInstance();
final TextView statusText = (TextView) rootView.findViewById(R.id.status_value);
final TextView nameText = (TextView) rootView.findViewById(R.id.name_value);
final TextView emailText = (TextView) rootView.findViewById(R.id.email_value);
final ImageView avatarView = (ImageView) rootView.findViewById(R.id.avatar);
if (gigya.getSession() != null){
if (gigya.getSession().isValid()) {
MainActivity parent = (MainActivity) getActivity();
GSObject user = parent.getUser();
// Retrieve the user if it's not set. (Reloaded app with active session)
if (user == null) {
GSResponseListener resListener = new GSResponseListener() {
#Override
public void onGSResponse(String method, GSResponse response, Object context) {
try {
if (response.getErrorCode()==0) { // SUCCESS! response status = OK
MainActivity parent = (MainActivity) getActivity();
Log.w("Gigya-Android-Demos", "Successfully set user");
parent.setUser(response.getData());
setLoggedIn(statusText, nameText, emailText, avatarView, response.getData());
} else { // Error
Log.w("Gigya-Android-Demos", "GSResponse: 'getAccountInfo' returned an error");
Log.w("Gigya-Android-Demos", response.getErrorMessage());
}
} catch (Exception ex) { ex.printStackTrace(); }
}
};
GSAPI.getInstance()
.sendRequest("accounts.getAccountInfo", null, resListener, null );
} else {
// Grab the user data
setLoggedIn(statusText, nameText, emailText, avatarView, user);
}
} else {
setLoggedOut(statusText, nameText, emailText, avatarView);
}
} else {
setLoggedOut(statusText, nameText, emailText, avatarView);
}
}
public void setLoggedOut(TextView status, TextView name, TextView email, ImageView avatar) {
status.setText(getString(R.string.logged_out));
name.setText(getString(R.string.null_value));
email.setText(getString(R.string.null_value));
setUnknownAvatar(avatar);
}
public void setLoggedIn(TextView status, TextView name, TextView emailView, ImageView avatar, GSObject user) {
status.setText(getString(R.string.logged_in));
try {
GSObject profile = user.getObject("profile");
String first = profile.getString("firstName");
String last = profile.getString("lastName");
String email = profile.getString("email");
if (profile.containsKey("photoURL")) {
setAvatar(avatar,profile.getString("photoURL"));
} else {
setUnknownAvatar(avatar);
}
name.setText(first + " " + last);
emailView.setText(email);
} catch (Exception ex) {
Log.w("Gigya-Android-Demos", "Something went horribly wrong with the user!");
ex.printStackTrace();
}
}
You should notice the use of getData() and GSObject classes throughout the example provided. Using this method of making a request, you should be able to examine the response data including the regToken.
I need help with Parse Android API and images uploading/updating. User in my app can create event that has 1 or more images related to that event. So, this images are stored as array object that have parse files.
User can edit images that he added for that event. So, user might want to delete image or to add a new image. So, there I have problem, how I can edit array to delete specific image.
My idea was to download all images on the phone, and when user add/delete image update it locally and then upload again all images to Parse and update that array of images, but it seems that is not working properly, since I get only one image uploaded.
How I can solve this problem, any idea is appreciated.
for (int i = 0; i < ImagesSingleton.getInstance().getBytesList().size(); i++) {
String fileName = FileHelper.getFileName(getActivity(), ImagesSingleton.getInstance().getUrisList().get(i), "image");
byte[] b = ImagesSingleton.getInstance().getBytesList().get(i);
final ParseFile imgFile = new ParseFile(fileName, ImagesSingleton.getInstance().getBytesList().get(i));
imgFile.saveInBackground(new SaveCallback() {
#Override
public void done(com.parse.ParseException e) {
if (e == null) {
listOfFiles.add(imgFile);
if (listOfFiles.size() == ImagesSingleton.getInstance().getUrisList().size()) {
offer.put(ParseConstants.OFFER_PICTURES, listOfFiles);
offer.saveInBackground(new SaveCallback() {
#Override
public void done(com.parse.ParseException e) {
if (e == null) {
mProgressDialog.dismiss();
Toast.makeText(getActivity(), "Sucess saving", Toast.LENGTH_SHORT).show();
ImagesSingleton.getInstance().reset();
transferToRadar();
} else {
mProgressDialog.dismiss();
Toast.makeText(getActivity(), getResources().getString(R.string.error) + e.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
}
}
});
}
}
}
});
}
I think it is quite clear in documentation how to delete an element(s) from an Array column in Parse. You simply have to send the list of the files you want to be removed from the Array like this:
offer.removeAll(ParseConstants.OFFER_PICTURES, listOfFilesToRemove);
offer.saveInBackground();
I need to know how to deal with a syncadapter and paginated response from Rest Server. I'm making one android app that retrieves data collection. Each page comes with 20 items and I'm retrieving all my items in one request now. I think that the best way that I can do it is retrieve one page and when, for example, scrolling to the end of the list view making another request with the syncAdapter but I not sure.
I was searching how to deal in android with pagination in REST but I didn't find anything useful. I wanna know if someone can help me.
Thank you.
Here is an example that how I'm retrieving item now.
public ArrayList<ContentProviderOperation> parse(String json) throws IOException, NullPointerException {
final ArrayList<ContentProviderOperation> batch = new ArrayList<ContentProviderOperation>();
AccountManager manager = AccountManager.get(mContext);
Account account = ((KipptApplication)mContext.getApplicationContext()).getCurrentAccount();
String authToken = manager.peekAuthToken(account, AuthenticatorActivity.PARAM_AUTHTOKEN_TYPE);
Header[] headers = new Header[]{
new BasicHeader(KipptConstants.API_USERNAME_KEY,account.name),
new BasicHeader(KipptConstants.API_TOKEN_KEY,authToken)
};
Gson gson = new Gson();
Type responseType = new TypeToken<Response<ClipObject>>() {}.getType();
Response<ClipObject> inbox = gson.fromJson(json,responseType);
List<ClipObject> clips = inbox.getObjects();
String response = null;
String next = inbox.getMeta().getNext();
while(next !=null){
try {
Log.d(TAG,"Fetching more clips from: " + next);
response = HttpHelper.getHttpResponseAsString(KipptConstants.DOMAIN_URL +
next, null, headers);
inbox = gson.fromJson(response,responseType);
/*Updating next uri*/
next = inbox.getMeta().getNext();
if(!inbox.getObjects().isEmpty()){
clips.addAll(inbox.getObjects());
}else{
Log.d(TAG,"No more clips");
break;
}
} catch (PersonalizedException e) {
Log.e(TAG,e.toString());
e.printStackTrace();
}
}
for(ClipObject clip : clips){
if(mKipptDAO.isClipInDb(mContext.getContentResolver(),clip.getId(),true)== null){
Log.i(TAG,"Adding new clip");
/*Parsing clip*/
parseClip(clip,batch,false /*Clip isn't in database so update=false*/);
/*Parsing media*/
parseMedia(clip.getMedia(),clip.getId(),batch,false);
/*Parsing comments if clip contains it*/
if(clip.getCommentObjects().getCount()>0) {
List<CommentObject> comments = clip.getCommentObjects().getListElements();
for(CommentObject comment: comments){
parseComments(comment,clip.getId(),batch,false);
}
}
/*TODO Parse Likes*/
/*Parsing user creator*/
parseCreator(clip.getUserCreator(),batch,false);
}else{
Log.i(TAG,"Modifying clip");
/*Clip is in database*/
if(!(clip.getUpdated()<= timestamp)){
/*Parsing clip and update it in database*/
parseClip(clip,batch,true);
/*Parsing media and update it in database*/
parseMedia(clip.getMedia(),clip.getId(),batch,true);
/*Parsing comments and update it in database*/
if(clip.getCommentObjects().getCount()>0) {
List<CommentObject> comments = clip.getCommentObjects().getListElements();
for(CommentObject comment: comments){
parseComments(comment,clip.getId(),batch,true);
}
}
/*TODO parse likes*/
/*Parse Creator*/
parseCreator(clip.getUserCreator(),batch,true);
}
}
/*Updating timestamp*/
if(timestamp<=clip.getUpdated())timestamp = clip.getUpdated();
}
/*Saving timestamp modified value in preferences file*/
this.sharedPreferences.edit().putLong(KipptConstants.loadTimeStamp(currentFragmentIndex), timestamp).commit();
return batch;
}
for using SyncAdapter suggested you try this.
also for detect end of list in RecyclerView using this:
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
// When went to the end of the list, load more posts
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
if (linearLayoutManager.findLastVisibleItemPosition() >= linearLayoutManager.getItemCount() - 1) {
// Grow List
}
}
}
I have two activities and two ParseObjects respectively. In one activity I'm saving 3 strings and in another activity I'm saving Image to the ImageView. Its getting successfully saved to Parse.com but with different ObjectIds. I want the Image to be saved in other table. and then get the image based on the mobile number. I have searched the documentation referred in the Parse.com but not able to resolve this.
final ParseObject dataObject = new ParseObject("DataObject");
dataObject.put("name", name);
dataObject.put("mobilenumber", mobileNumber);
dataObject.put("occupation", occup);
dataObject.saveInBackground(new SaveCallback() {
public void done(ParseException e) {
if (e == null) {
// Success!
String objectId = dataObject.getObjectId();
} else {
// Failure!
}
}
});
Toast.makeText(getBaseContext(), "Data successfully saved "+ objectId, Toast.LENGTH_LONG).show();
This is the first activity. In the next activity I'm saving an image. I want the ObjectId but its says NULL everytime. Pls Help.
You can send the mobile number with intent to your next activity like :
public void onClick(View arg0) {
progressDialog = ProgressDialog.show(LoadImg.this, "",
"Saving Image...", true);
try {
image = readInFile(path);
}
catch(Exception e) {
e.printStackTrace();
}
ParseFile file = new ParseFile("picturePath.png", image);
file.saveInBackground();
ParseObject imgupload = new ParseObject("Image");
imgupload.put("ImageFile", file);
imgupload.put("Mobilenumber", mob);
// Create the class and the columns
and in the activity you can fetch the mobile number from the intent like :
ParseQuery<ParseObject> query = new ParseQuery<ParseObject>("Image");
mobileNumber = mbltxt.getText().toString();
query.whereEqualTo("Mobilenumber", mobileNumber);
ob = query.find();
How about this.
You can send the three strings as a bundle from the first activity to the next(second) activity using intent.putExtras(Bundle) or Intent.putExtra(String, String) and then in the second activity, get the extras and then save the strings and the image together into a ParseObject. This will also reduce the number of API requests to Parse.