EDIT:
I asked a similar question a day before and I wrote this post based on information I gathered since that question -
First Cache Question. I know they are similar but this question is more concise to avoid extra information. I also didn't want to delete that post since it was answered, even though the answer didn't suffice.
I use a recyclerview to show photos I get from google places api. I know that I am not allowed to legally cache photos outside of runtime. I didn't know that was happening until I randomly opened my phone's gallery to see a lot of copies of the photos I get from google.
My first guess was that my use of Picasso was the issue so I added code to fix it,
.memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE)
.networkPolicy(NetworkPolicy.NO_CACHE)
finding these in StackOverflow was pretty simple, but this didn't fix anything except that now it seems to only download them once especially when I delete them. I believe I eliminated the possible issues and am outlining the last one in this question.
private Uri getImageUri(Context inContext, Bitmap inImage) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, "Title", null);
return Uri.parse(path);
}
#Override
public void onBindViewHolder(#NonNull VenueViewHolder venueViewHolder, int i) {
Collections.sort(vIAL, (o1, o2) -> o1.getVenueName().compareToIgnoreCase(o2.getVenueName()));
VenueItem currentItem = vIAL.get(i);
Picasso.with(context)
.load(getImageUri(context, currentItem.getVenueImage()))
.fit()
.memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE)
.networkPolicy(NetworkPolicy.NO_CACHE)
.into(venueViewHolder.vIV);
venueViewHolder.vTV.setText(currentItem.getVenueName());
Log.i(TAG, "The photo should have been on screen");
}
The URI method getImageUri is something I found as an answer to another problem I had, that I needed a URI to implement the Picasso library so that I can manipulate the photos before displaying them.
My question is - How do I remove the photos when the app closes?
UPDATE:
I changed my tactic to see what would happened and used Glide
#Override
public void onBindViewHolder(#NonNull VenueViewHolder venueViewHolder, int i) {
Collections.sort(vIAL, (o1, o2) -> o1.getVenueName().compareToIgnoreCase(o2.getVenueName()));
VenueItem currentItem = vIAL.get(i);
Glide.with(context)
.load(currentItem.getVenueImage())
.into(venueViewHolder.vIV);
venueViewHolder.vTV.setText(currentItem.getVenueName());
}
and it gave a fatal Error
E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 4344032)
This was one of the errors and it didn't occur the first time I ran this new code but it got worse the second and third time I ran it.
I shifted my code based on an answer I got early from #Padmini S but they used a url in the load part and I pass a bitmap because for the life of me I can't figure out how to get a URL from Google Places API instead of the code they provide in
Google Place Photos.
I'm relatively new to coding so this is me trying to piece together what I need to learn more. I'm just out of ideas of what to search for so I ask here,
based on the new information I gathered from the answer, can I replace
MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, "Title", null);
in my code so that my photos don't get saved to my phone's photos?
Final Update
I ended up rewriting a lot of the code surrounding this and deleting this code. I ended up making an arraylist class to hold the array list for the duration of runtime and it let me remove most of the extra code I wrote out of ignorance.
I really don't know whether it'll solve your problem or not , but you are storing the images in device local storage here,
private Uri getImageUri(Context inContext, Bitmap inImage) {
String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, "Title", null);
}
I have never used google places api but usually apis will return you with an image url you can store that url in POJO class and display it directly in recyclerview row image view like I am doing in below code,
public void onBindViewHolder(#NonNull ViewHolder viewHolder, final int i) {
viewHolder.description.setText(links.get(i).getTitle());
Glide.with(context).load(links.get(i).getImage_url()).into(viewHolder.image);
}
Related
So I am doing an app that lets you take images (inside CameraActivity, using CameraX) and saves them to local storage. The images are later displayed in a RecyclerView, getting them by their URI.
My issue is that as soon as I open the fragment that contains the recyclerview with the images it gets very very slow. The images are small and don't necessarily need to be in good quality, so I thought of maybe compressing them or just saving them in lower quality right when they are taken to make the loading process faster. Is there any way I can do that right here at this point in the code?
This is some relevant code from CameraActivity:
imgView_cameraTrigger.setOnClickListener(v -> {
SimpleDateFormat mDateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US);
File file = new File(getExternalFilesDir(Environment.DIRECTORY_DCIM), mDateFormat.format(new Date())+ ".jpg");
ImageCapture.OutputFileOptions outputFileOptions = new ImageCapture.OutputFileOptions.Builder(file).build(); // saves image file
imageCapture.takePicture(outputFileOptions, executor, new ImageCapture.OnImageSavedCallback () {
#Override
public void onImageSaved(#NonNull ImageCapture.OutputFileResults outputFileResults) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
Toast.makeText(CameraActivity.this, "image saved successfully", Toast.LENGTH_SHORT).show();
// Toast.makeText(CameraActivity2.this, "PATH: " + file.getAbsolutePath(), Toast.LENGTH_SHORT).show();
Uri uri = Uri.fromFile(file);
ImageView preview = TrackFragment.getImageViewInTrackFragment();
preview.setImageURI(uri); // display taken image in imageview in track fragment
TrackFragment.setImgPreviewUri(uri); // pass uri to TrackFragment to use it there
CameraActivity.this.finish(); // exit camera activity
}
});
}
#Override
public void onError(#NonNull ImageCaptureException error) {
error.printStackTrace();
}
});
});
I thought of maybe compressing them or just saving them in lower quality right when they are taken to make the loading process faster
You probably can give resolution suggestions to CameraX to have it take a lower-resolution image, if that is what you mean. That would tie to code outside of your question.
However, a large part of your problem also lies here:
preview.setImageURI(uri); // display taken image in imageview in track fragment
The documentation for setImageURI() states:
This does Bitmap reading and decoding on the UI thread, which can cause a latency hiccup
In other words, using setImageURI() leads to poor performance and is rarely recommended.
Please use Glide, Picasso, or another image-loading library. Not only can they do the image loading on a background thread, but they can also automatically down-sample the image to fit your ImageView, improving loading speeds. They can also show a placeholder image while the image is being loaded, cache images in memory to reduce redundant image loads, etc.
FWIW, I demonstrate the use of Glide for image loading in this section of this free book, though changes in the US National Weather Service API may mean that the sample code itself does not work correctly now as it did when I published that final edition.
I have an android resume building application. I want to generate a PDF of size A4 from my view. Here's how my layout looks like - At the top I have a Top App Bar, and the whole view in encapsulated in drawer. The main part which contains user's details is encapsulated in nestedScrollView, which contains multiple LinearLayout and TextView. In this screenshot below, I have populated it with mock data, but in actuality, I am fetching data from the Firebase Realtime Database and displaying it on the UI.
I tried to understand iTextPdf solution and multiple question of similar type that has been asked here, but I couldn't find something solid. Please help me out, it would be of great help.
Also, please don't close this question by giving a reason that the question doesn't contain any code. It doesn't because I don't have any. I am trying to solve this problem from scratch. I have tried to describe my problem as much as I could.
try this:
create a WebView and copy the text of your edittext in it:
webview.loadData(youredittext.gettext().tostring, "text/html", "UTF-8");
and convert webview to pdf by below function:
private void createWebPrintJob(WebView webView) {
PrintManager printManager = (PrintManager) this
.getSystemService(Context.PRINT_SERVICE);
PrintDocumentAdapter printAdapter =
webView.createPrintDocumentAdapter();
String jobName = getString(R.string.app_name) + " Print Test";
if (printManager != null) {
printManager.print(jobName, printAdapter,
new PrintAttributes.Builder().build());
}
}
after that user can select page size for example A4
There are a lot of libraries that convert layouts to PDF, but let's opt for popular one so we could find answers if we're stuck.
The libraries I listed works like so : They take screenshot of your layout as bitmap image and convert it to pdf.
- 1st solution: iTextPDF https://github.com/itext/itext7 (New Version).
check this detailed tutorial which treates also the case of taking screenshot of a scrollview https://www.codeproject.com/Articles/989236/How-to-Convert-Android-View-to-PDF-2
and this stackoverflow answer https://stackoverflow.com/a/29731275/12802591
- 2nd solution: PdfMyXML library https://github.com/HendrixString/Android-PdfMyXml just follow the steps in the documentation.
They may be other solutions, but these are the popular ones.
Let Me know if it works for you and also if you're stuck. Thank you!
Relevant code:
YouTubeThumbnailView first_video = (YouTubeThumbnailView) findViewById(R.id.main_video);
first_video.initialize(Config.YOUTUBE_API, new YouTubeThumbnailView.OnInitializedListener() {
#Override
public void onInitializationSuccess(YouTubeThumbnailView youTubeThumbnailView, YouTubeThumbnailLoader youTubeThumbnailLoader) {
final String video = getResources().getString(R.string.principal_funcoes);
youTubeThumbnailLoader.setVideo(video);
}
The time it takes for the method 'youTubeThumbnailLoader.setVideo(String s)" to work is absurd.
It takes 30+ seconds for a thumbnail to show up, with full cabled connection (100mbps).
It's definitely impossible for a user to wait more than 2 seconds for the thumbnail to show up, and have a completely blank screen while he waits for that to happen.
What can I do to load the video thumbnail any faster, or at least make YouTubeThumbnailView show a loading image while it fetches the thumbnail?
You can use direct youtube api urls for getting youtube thumbnails and they are way to faster too. here are urls you can try.
Start:-- It is only give you default size thumbnails.
https://ytimg.googleusercontent.com/vi/<insert-youtube-video-id-here>/default.jpg
For the high quality version of the thumbnail use a url similar to this:
https://ytimg.googleusercontent.com/vi/<insert-youtube-video-id-here>/hqdefault.jpg
There is also a medium quality version of the thumbnail, using a url similar to the HQ:
https://ytimg.googleusercontent.com/vi/<insert-youtube-video-id-here>/mqdefault.jpg
For the standard definition version of the thumbnail, use a url similar to this:
https://ytimg.googleusercontent.com/vi/<insert-youtube-video-id-here>/sddefault.jpg
For the maximum resolution version of the thumbnail use a url similar to this:
https://ytimg.googleusercontent.com/vi/<insert-youtube-video-id-here>/maxresdefault.jpg
It helps me to develop youtube application, Hope it also help you.
I'm making this netflix style app in which images are loaded into different categories. Let's say Dog videos (has 15 images), Cat videos (15 images), etc... All the images are loaded from a URL, it kind of takes a while for all to load. I was wondering if there was anything I could do to speed up the process? Or maybe show an empty container then fill it as the images load (that would be cool).
This is what I have done:
I have multiple async calls in one Activity, (1 async call per category)
JSONTask1 dogTask = new JSONTask1();
JSONTask2 catTask = new JSONTask2();
JSONTask3 pigTask = new JSONTask3();
JSONTask4 horseTask = new JSONTask4();
dogTask.execute("");
catTask.execute("");
pigTask.execute("");
horseTask.execute("");
I have all of those in a row in my actual code. Thanks.
I would use the "proxy pattern". Basically, you need to create a class that contains the minimal informations required for the display. In which, you have a preview image.
When ever you load everything you start by showing the preview content, ie : a loading gif for everypicture with the title of the movie or whatever. and basically the proxy would have a "loadImage" method that would make an ajax call or async call and the photos would load one by one. Plus, to make the loading easier, make sure the photos are not oversized.
You can see Picasso answers , in picasso i suggest you this way :
Picasso.with(getApplicationContext()).load("your url").placeholder(R.drawable.your_place_holder).error(R.drawable.showing_when_error_occured)
.into(imageView, new Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError() {
}
});
Also another suggestion from me : convert your thumb images to base64 format in backend, then firstly retrieve your thumbs and show them. Then start an async task and change images when successfull.
Like whatsapp. In whatsapp you have thumb images they have so low resolution and super fast. When you click image if you have internet connection they load actual thumb images, and click again they load larger image.
Picasso website :http://square.github.io/picasso/
Load them asynchronously with Picasso, you can even show a placeholder image until the real one is loaded
Loading images with Picasso is seemingly so easy, until I hit this roadblock. Not sure why! I can load photos from contacts via PHOTO_URI if the contacts only have a thumbnail, or, if I instead ask for PHOTO_THUMBNAIL_URI specifically.
#Override
public void bindView(View view, Context context, Cursor cursor) {
ImageView icon = (ImageView)view.findViewById(R.id.ContactImage);
String photoUri = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.PHOTO_URI));
if (photoUri == null) {
icon.setImageDrawable(null);
} else {
Picasso.with(context).load(photoUri).into(icon);
}
}
For what it's worth: if I use Picasso.with(context).load(photoUri).placeholder(R.drawable.placeholder).error(R.drawable.error).into(icon); then I see the placeholder image in the place of every contact who has a high res image. I never see an "error" picture. If I revert back to just using icon.setImageURI(Uri.parse(photoUri)); then I see the high res contact images again just fine. (But then I don't have a snazzy async caching picture loader!)
UPDATE: Thanks to #copolii and his answers below, the following now works flawlessly with Picasso 2.1.1:
#Override
public void bindView(View view, Context context, Cursor cursor) {
Long id = cursor.getLong(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID));
Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, id);
String photoUri = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.PHOTO_URI));
ImageView icon = (ImageView)view.findViewById(R.id.ContactImage);
if (photoUri == null) {
icon.setImageDrawable(null);
} else {
Picasso
.with(context)
.load(contactUri)
.into(icon);
}
}
This loads the higher-res photo, if there is one, and if not, shows the low-res photo, and if there is no photo set for a contact, it's set to a blank / null.
Have you tried using a contact uri?
That last boolean parameter in openContactPhotoInputStream promises to get you the high res photo if one is available.
Instead of using a photo uri use a contact uri or a contact lookup uri.
UPDATE
Since the question has been answered, I though I'd post the relevant details here:
A small test app is posted here (You need Android Studio): https://github.com/copolii/PicassoContactsTest
If you set both a placeholder and an error icon, the error icon is displayed for contacts who do not have a picture. I'd recommend setting the social face guy as your place-holder and no error icon. That way, your place-holder stays on if the contact has no picture.
If you do want to differentiate between the two, choose your error icon with the above in mind (i.e. don't use a big red OMFG error indicator).
--- Previous Content ---
Let me know if that helps.
I did the work for the contacts photo loading and unless I'm missing something, you should get the high resolution picture (API 14+) automatically:
if (SDK_INT < ICE_CREAM_SANDWICH) {
return openContactPhotoInputStream(contentResolver, uri);
} else {
return openContactPhotoInputStream(contentResolver, uri, true);
}
It seems that the openContactPhotoInputStream doesn't like the PHOTO_URI.
Android Docs: openContactPhotoInputStream
If the URIs are distinguishable I can easily add support for PHOTO_URI as well (I have to find out how to load it first though). I'm already determining if the given uri is a contact photo uri or a contact lookup uri (older android versions do not like lookup uris being fed into openContactPhotoInputStream so I have to dereference the lookup uri into a contact uri before passing it to openContactPhotoInputStream).
I hope this helps.