I am using the open source library: https://code.google.com/p/flickrj-android/ and there is an example how do I get photos from flickr. Main problem is that I get only public photos. How can I manage getting private streams/photos?
Did anyone managed to get private streams?
With Flickrj-android you'd want to use this method:
Flickr flickr = new Flickr(API_KEY,SHARED_SECRET,new REST());
Set<String> extras = new HashSet();
// A set of extra info we want Flickr to give back. Go to the API page to see the other size options available.
extras.add("url_o");
extras.add("original_format");
//A request for a list of the photos in a set. The first zero is the privacy filter,
// the second is the Pages, and the third is the Per-Page (see the Flickr API)
PhotoList<Photo> photoList = flickr.getPhotosetsInterface().getPhotos(PHOTOSET_ID, extras, 0, 0, 0);
//We'll use the direct URL to the original size of the photo in order to download it. Remember: you want to make as few requests from flickr as possible!
for(Photo photo : photoList){
//You can also get other sizes. Just ask for the info in the first request.
URL url = new URL(photo.getOriginalSize().getSource());
InputStream is = url.openStream();
OutputStream os = new FileOutputStream(PATH_OF_FOLDER + photo.getTitle() + "." + photo.getOriginalFormat());
byte[] b = new byte[2048];
int length;
while ((length = is.read(b)) != -1) {
os.write(b, 0, length);
}
is.close();
os.close();
}
Use this method for a single-photo inputstream.
InputStream inputStream = flickr.getPhotosInterface().getImageAsStream(flickr.getPhotosInterface().getPhoto(PHOTO_ID), Size.ORIGINAL);
I'm not very familiar with Java and that framework but will try to help.
I found next method name in that framework:
public class PeopleInterface {
public static final String METHOD_GET_PHOTOS = "flickr.people.getPhotos";
/**
* Returns photos from the given user's photostream. Only photos visible the
* calling user will be returned. this method must be authenticated.
*
* #param userId
* #param extras
* #param perpage
* #param page
* #return
* #throws IOException
* #throws FlickrException
* #throws JSONException
*/
public PhotoList getPhotos(String userId, Set<String> extras, int perPage,
int page)
From Flick API docs I found next:
flickr.people.getPhotos Return photos from the given user's photostream. Only photos visible to the calling user will be returned.
This method must be authenticated; to return public photos for a user,
use flickr.people.getPublicPhotos.
So, it mean that you must be authenticated with 'read' permissions to get your private pohotos (your account).
You can also get private photos of some users only in case if you are contact/friend of that user.
Related
I received the following warning via email from Facebook Developers a few days ago:
As part of our Graph API 8.0 release, we announced changes to how
developers can access User Picture and FB/IG OEmbed endpoints. We are
including more information about these changes below so you can make
the appropriate updates to your apps.
Facebook will now require client or app access tokens to access a
user’s profile picture when querying against user IDs. Beginning on
October 24, 2020, queries for profile pictures made against user IDs
without an access token will return a generic silhouette rather than a
profile picture. While client or app tokens will be required for user
ID queries, they will continue to be a best practice (and not
required) for ASID queries for the time being. You can read more about
this change in our developer documentation for User Picture.
Going by the above message, I'm not sure whether my block of code will be affected. Here is the code:
val profilePicUrl = Profile.getCurrentProfile().getProfilePictureUri(600, 600).toString()
That line gets the URI of the user's profile image after they have logged in.
Source code from the SDK:
/**
* Getter for the profile that is currently logged in to the application.
* #return The profile that is currently logged in to the application.
*/
public static Profile getCurrentProfile()
{
return ProfileManager.getInstance().getCurrentProfile();
}
/**
* Getter for the Uri of the profile picture.
*
* #param width The desired width for the profile picture.
* #param height The desired height for the profile picture.
* #return The Uri of the profile picture.
*/
public Uri getProfilePictureUri(
int width,
int height) {
return ImageRequest.getProfilePictureUri(this.id, width, height);
}
public static Uri getProfilePictureUri(
String userId,
int width,
int height) {
Validate.notNullOrEmpty(userId, "userId");
width = Math.max(width, UNSPECIFIED_DIMENSION);
height = Math.max(height, UNSPECIFIED_DIMENSION);
if (width == UNSPECIFIED_DIMENSION && height == UNSPECIFIED_DIMENSION) {
throw new IllegalArgumentException("Either width or height must be greater than 0");
}
Uri.Builder builder =
Uri.parse(ServerProtocol.getGraphUrlBase())
.buildUpon()
.path(String.format(
Locale.US, PATH,
FacebookSdk.getGraphApiVersion(),
userId));
if (height != UNSPECIFIED_DIMENSION) {
builder.appendQueryParameter(HEIGHT_PARAM, String.valueOf(height));
}
if (width != UNSPECIFIED_DIMENSION) {
builder.appendQueryParameter(WIDTH_PARAM, String.valueOf(width));
}
builder.appendQueryParameter(MIGRATION_PARAM, MIGRATION_VALUE);
I'm not sure whether I will be affected as I don't specifically use the Graph API?
Is someone able to shed some light on this?
I'm using Azure Storage with the Android API. I'm trying to copy one block blob from one location to another (in the SAME blob container).
However, when I make the copy I get a "CannotVerifyCopySource" error after invoking the startCopy method.
Example Code:
private void sample(String path1, String path2, File file) {
CloudBlockBlob blob1 = container.getBlockBlobReference(path1);
CloudBlockBlob blob2 = container.getBlockBlobReference(path2);
blob1.upload(new FileInputStream(file), file.length());
blob1.startCopy(blob2);
}
Any ideas on what might be the problem?
Best regards,
see source about startCopy below. I think you should use blob2.startCopy(blob1) here.
/**
* Requests the service to start copying a block blob's contents, properties, and metadata to a new block blob.
*
* #param sourceBlob
* A <code>CloudBlockBlob</code> object that represents the source blob to copy.
*
* #return A <code>String</code> which represents the copy ID associated with the copy operation.
*
* #throws StorageException
* If a storage service error occurred.
* #throws URISyntaxException
*/
#DoesServiceRequest
public final String startCopy(final CloudBlockBlob sourceBlob) throws StorageException, URISyntaxException {
return this.startCopy(sourceBlob, null /* sourceAccessCondition */,
null /* destinationAccessCondition */, null /* options */, null /* opContext */);
}
I am working on an application (Android 4.4 -- API 20) where I am generating a report in HTML format. I use the WebView object to display the report in my app.
What I would like to be able to do is convert this WebView into a pdf document.
I have been able to convert it using PdfDocument, and doing .draw onto the page from the WebView object. I save the file, and this works, except that the result is a single page document. There are no page breaks.
View content = (View) webView;
PrintAttributes pdfPrintAttrs = new PrintAttributes.Builder().
setColorMode(PrintAttributes.COLOR_MODE_MONOCHROME).
setMediaSize(PrintAttributes.MediaSize.NA_LETTER.asLandscape()).
setResolution(new Resolution("zooey", PRINT_SERVICE, 300, 300)).
setMinMargins(PrintAttributes.Margins.NO_MARGINS).
build();
PdfDocument document = new PrintedPdfDocument(mContext,pdfPrintAttrs);
PageInfo pageInfo = new PageInfo.Builder(webView.getMeasuredWidth(), webView.getContentHeight(), 1).create();
Page page = document.startPage(pageInfo);
content.draw(page.getCanvas());
document.finishPage(page);
If I change it so that I use the PrintedPdfDocumet and don't specify the PageInfo I only get the viewable part of the WebView object.
View content = (View) webView;
PrintAttributes pdfPrintAttrs = new PrintAttributes.Builder().
setColorMode(PrintAttributes.COLOR_MODE_MONOCHROME).
setMediaSize(PrintAttributes.MediaSize.NA_LETTER.asLandscape()).
setResolution(new Resolution("zooey", PRINT_SERVICE, 300, 300)).
setMinMargins(PrintAttributes.Margins.NO_MARGINS).
build();
PrintedPdfDocument document = new PrintedPdfDocument(mContext,pdfPrintAttrs);
Page page = document.startPage(0);
content.draw(page.getCanvas());
document.finishPage(page);
If I use the PrintManager and create a print adapter from the WebView object with createPrintDocumentAdapter, I can select the "Save as PDF" option and the resulting pdf file has the page breaks as I specify in the CSS of the original web page.
PrintManager printManager = (PrintManager) getSystemService(Context.PRINT_SERVICE);
PrintDocumentAdapter printAdapter = webView.createPrintDocumentAdapter();
String jobName = getString(R.string.app_name) + " Report "
+ reportName;
PrintAttributes printAttrs = new PrintAttributes.Builder().
setColorMode(PrintAttributes.COLOR_MODE_MONOCHROME).
setMediaSize(PrintAttributes.MediaSize.NA_LETTER.asLandscape()).
setMinMargins(PrintAttributes.Margins.NO_MARGINS).
build();
PrintJob printJob = printManager.print(jobName, printAdapter,
printAttrs);
My question is: can I specify that I want the PrintManager to perform a "Save as PDF" and provide the name and location of the resulting file so that there is no interaction with the user?
Or: Is there a way I can convert my WebView object into a PDF and allow for page breaks.
It might be a late answer but I was also in need of similar solution with Print Framework so far, and I splitted the Pdf Document into pages with the code below.
As far as I can see, you cannot really make the WebView or Pdf Document splits your pdf file into pages in a smart way (not cutting the text or image). But what we can do is to create Pages in a ratio of A4 or Letter size, so it can fit into print out paper format.
But there is another issue I'm facing. The code below works as expected in Android 4.4 but not in later versions. In Android-L, only the visible part of WebView is drawn into Pdf File, but white blank pages for the rest of the HTML in WebView.
According to documentation,
public static void enableSlowWholeDocumentDraw ()
For apps targeting the L release, WebView has a new default behavior that reduces memory footprint and increases performance by intelligently choosing the portion of the HTML document that needs to be drawn. These optimizations are transparent to the developers. However, under certain circumstances, an App developer may want to disable them:
When an app uses onDraw(Canvas) to do own drawing and accesses portions of the page that is way outside the visible portion of the page.
When an app uses capturePicture() to capture a very large HTML document. Note that capturePicture is a deprecated API.
Enabling drawing the entire HTML document has a significant performance cost. This method should be called before any WebViews are created.
I've created a Bug Report, and commented on a similar bug report HERE, but no response so far. But until then, you can use the code below.
/**
* Creates a PDF Multi Page Document depending on the Ratio of Letter Size.
* This method does not close the Document. It should be Closed after writing Pdf Document to a File.
*
* #return
*/
private PdfDocument createMultiPagePdfDocument(int webViewWidth, int webViewHeight) {
/* Find the Letter Size Height depending on the Letter Size Ratio and given Page Width */
int letterSizeHeight = getLetterSizeHeight(webViewWidth);
PdfDocument document = new PrintedPdfDocument(getActivity(), getPrintAttributes());
final int numberOfPages = (webViewHeight/letterSizeHeight) + 1;
for (int i = 0; i < numberOfPages; i++) {
int webMarginTop = i*letterSizeHeight;
PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(webViewWidth, letterSizeHeight, i+1).create();
PdfDocument.Page page = document.startPage(pageInfo);
/* Scale Canvas */
page.getCanvas().translate(0, -webMarginTop);
mWebView.draw(page.getCanvas());
document.finishPage(page);
}
return document;
}
/**
* Calculates the Letter Size Paper's Height depending on the LetterSize Dimensions and Given width.
*
* #param width
* #return
*/
private int getLetterSizeHeight(int width) {
return (int)((float)(11*width)/8.5);
}
Not sure if this will solve your page-break issues, but have you considered using the open-source wkHTMLtoPDF library (http://wkhtmltopdf.org/) for the conversion from HTML to PDF? We have used it extensively by creating a micro-service that we pass the HTML code to, then have the service convert it to PDF and return the link to the PDF, or alternatively have it return the PDF (depending on size). I know using an external service for the conversion might be a pain (or maybe you don't have internet access from the device), but if that's not an issue, then this could be an option. There may be other APIs available to do this conversion as well. One such API is Neutrino API. There are many others - you can search for APIs using one of these API search engines:
apis.io
Progammable Web
Public APIs
After spending enormous time with this problem, I used DexMaker to implement non public abstract callbacks and came up with this:
#Override
protected void onPreExecute() {
super.onPreExecute();
printAdapter = webView.createPrintDocumentAdapter();
}
#Override
protected Void doInBackground(Void... voids) {
File file = new File(pdfPath);
if (file.exists()) {
file.delete();
}
try {
file.createNewFile();
// get file descriptor
descriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_WRITE);
// create print attributes
PrintAttributes attributes = new PrintAttributes.Builder()
.setMediaSize(PrintAttributes.MediaSize.ISO_A4)
.setResolution(new PrintAttributes.Resolution("id", PRINT_SERVICE, 300, 300))
.setColorMode(PrintAttributes.COLOR_MODE_COLOR)
.setMinMargins(new PrintAttributes.Margins(0, 0, 0, 0))
.build();
ranges = new PageRange[]{new PageRange(1, numberPages)};
// dexmaker cache folder
cacheFolder = new File(context.getFilesDir() +"/etemp/");
printAdapter.onStart();
printAdapter.onLayout(attributes, attributes, new CancellationSignal(), getLayoutResultCallback(new InvocationHandler() {
#Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
if (method.getName().equals("onLayoutFinished")) {
onLayoutSuccess();
} else {
Log.e(TAG, "Layout failed");
pdfCallback.onPdfFailed();
}
return null;
}
}, cacheFolder), new Bundle());
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG, e != null ? e.getMessage() : "PrintPdfTask unknown error");
}
return null;
}
private void onLayoutSuccess() throws IOException {
PrintDocumentAdapter.WriteResultCallback callback = getWriteResultCallback(new InvocationHandler() {
#Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
if (method.getName().equals("onWriteFinished")) {
pdfCallback.onPdfCreated();
} else {
Log.e(TAG, "Layout failed");
pdfCallback.onPdfFailed();
}
return null;
}
}, cacheFolder);
printAdapter.onWrite(ranges, descriptor, new CancellationSignal(), callback);
}
/**
* Implementation of non public abstract class LayoutResultCallback obtained via DexMaker
* #param invocationHandler
* #param dexCacheDir
* #return LayoutResultCallback
* #throws IOException
*/
public static PrintDocumentAdapter.LayoutResultCallback getLayoutResultCallback(InvocationHandler invocationHandler,
File dexCacheDir) throws IOException {
return ProxyBuilder.forClass(PrintDocumentAdapter.LayoutResultCallback.class)
.dexCache(dexCacheDir)
.handler(invocationHandler)
.build();
}
/**
* Implementation of non public abstract class WriteResultCallback obtained via DexMaker
* #param invocationHandler
* #param dexCacheDir
* #return LayoutResultCallback
* #throws IOException
*/
public static PrintDocumentAdapter.WriteResultCallback getWriteResultCallback(InvocationHandler invocationHandler,
File dexCacheDir) throws IOException {
return ProxyBuilder.forClass(PrintDocumentAdapter.WriteResultCallback.class)
.dexCache(dexCacheDir)
.handler(invocationHandler)
.build();
}
I'm using Volley as my network stack in a project I'm working on in Android. Part of my requirements is to download potentially very large files and save them on the file system.
Ive been looking at the implementation of volley, and it seems that the only way volley works is it downloads an entire file into a potentially massive byte array and then defers handling of this byte array to some callback handler.
Since these files can be very large, I'm worried about an out of memory error during the download process.
Is there a way to tell volley to process all bytes from an http input stream directly into a file output stream? Or would this require me to implement my own network object?
I couldn't find any material about this online, so any suggestions would be appreciated.
Okay, so I've come up with a solution which involves editing Volley itself. Here's a walk through:
Network response can't hold a byte array anymore. It needs to hold an input stream. Doing this immediately breaks all request implementations, since they rely on NetworkResponse holding a public byte array member. The least invasive way I found to deal with this is to add a "toByteArray" method inside NetworkResponse, and then do a little refactoring, making any reference to a byte array use this method, rather than the removed byte array member. This means that the transition of the input stream to a byte array happens during the response parsing. I'm not entirely sure what the long term effects of this are, and so some unit testing / community input would be a huge help here. Here's the code:
public class NetworkResponse {
/**
* Creates a new network response.
* #param statusCode the HTTP status code
* #param data Response body
* #param headers Headers returned with this response, or null for none
* #param notModified True if the server returned a 304 and the data was already in cache
*/
public NetworkResponse(int statusCode, inputStream data, Map<String, String> headers,
boolean notModified, ByteArrayPool byteArrayPool, int contentLength) {
this.statusCode = statusCode;
this.data = data;
this.headers = headers;
this.notModified = notModified;
this.byteArrayPool = byteArrayPool;
this.contentLength = contentLength;
}
public NetworkResponse(byte[] data) {
this(HttpStatus.SC_OK, data, Collections.<String, String>emptyMap(), false);
}
public NetworkResponse(byte[] data, Map<String, String> headers) {
this(HttpStatus.SC_OK, data, headers, false);
}
/** The HTTP status code. */
public final int statusCode;
/** Raw data from this response. */
public final InputStream inputStream;
/** Response headers. */
public final Map<String, String> headers;
/** True if the server returned a 304 (Not Modified). */
public final boolean notModified;
public final ByteArrayPool byteArrayPool;
public final int contentLength;
// method taken from BasicNetwork with a few small alterations.
public byte[] toByteArray() throws IOException, ServerError {
PoolingByteArrayOutputStream bytes =
new PoolingByteArrayOutputStream(byteArrayPool, contentLength);
byte[] buffer = null;
try {
if (inputStream == null) {
throw new ServerError();
}
buffer = byteArrayPool.getBuf(1024);
int count;
while ((count = inputStream.read(buffer)) != -1) {
bytes.write(buffer, 0, count);
}
return bytes.toByteArray();
} finally {
try {
// Close the InputStream and release the resources by "consuming the content".
// Not sure what to do about the entity "consumeContent()"... ideas?
inputStream.close();
} catch (IOException e) {
// This can happen if there was an exception above that left the entity in
// an invalid state.
VolleyLog.v("Error occured when calling consumingContent");
}
byteArrayPool.returnBuf(buffer);
bytes.close();
}
}
}
Then to prepare the NetworkResponse, we need to edit the BasicNetwork to create the NetworkResponse correctly (inside BasicNetwork.performRequest):
int contentLength = 0;
if (httpResponse.getEntity() != null)
{
responseContents = httpResponse.getEntity().getContent(); // responseContents is now an InputStream
contentLength = httpResponse.getEntity().getContentLength();
}
...
return new NetworkResponse(statusCode, responseContents, responseHeaders, false, mPool, contentLength);
That's it. Once the data inside network response is an input stream, I can build my own requests which can parse it directly into a file output stream which only hold a small in-memory buffer.
From a few initial tests, this seems to be working alright without harming other components, however a change like this probably requires some more intensive testing & peer reviewing, so I'm going to leave this answer not marked as correct until more people weigh in, or I see it's robust enough to rely on.
Please feel free to comment on this answer and/or post answers yourselves. This feels like a serious flaw in Volley's design, and if you see flaws with this design, or can think of better designs yourselves, I think it would benefit everyone.
I have read many questions about Android, J2ME and RecordStore, but I still can't find the answer that could satisfy me.
I need to implement low-level part of my Java app that should work on different platforms, right now this is Android and J2ME, and in future it should work on PC too. I need to store simple data sets, that is almost similar to RecordStore in J2ME:
App should own several record stores with records, each record has:
the id (but it should be "my" id, not auto-returned one as it is in RecordStore),
the data (just a byte array).
I think I should write an Interface with needed methods, and each platform should have its own implementation of this Interface.
But this task seems to be very common (at least, for Android + J2ME), so, maybe there already is some lightweight implementation? I'm asking just because I don't like to re-invent the wheel.
And maybe some suggestions?
So, I wrote interface that does satisfy my requirements, with two implementations: for Android and J2ME.
Here is how does Interface look:
public interface ISDataStore {
/**
* Get number of records in data store.
*/
public int getNumRecords() throws SDataStoreException;
/**
* Get size of one record with specified id in bytes.
*
* #param record_id id of the record
*/
public int getRecordSize(int record_id) throws SDataStoreException;
/**
* Get record.
*
* #param record_id id of the record to read
* #param data byte array where to put the data
* #param offset offset in 'data' array from which should start to copy
*/
public void getRecord(int record_id, byte[] data, int offset) throws SDataStoreException;
/**
* Get record.
*
* #param record_id id of the record to read
*/
public byte[] getRecord(int record_id) throws SDataStoreException;
/**
* Resolves is record with specified id exists or not.
*
* #param record_id id of the record
* #return true if record exists, otherwise false
*/
public boolean isRecordExists(int record_id) throws SDataStoreException;
/**
* Put new record or update existing one.
*
* #param record_id id of the record
* #param data byte array of data
* #param offset offset in the data byte array
* #param length number of bytes to store
*
* #return true if operation was successful, otherwise false
*
*/
public boolean setRecord(int record_id, byte[] data, int offset, int length) throws SDataStoreException;
/**
* Delete the record.
*
* #param record_id id of the record
*
* #return true if operation was successful, otherwise false
*/
public boolean deleteRecord(int record_id) throws SDataStoreException;
/**
* Clear all the records.
*/
public void deleteAll() throws SDataStoreException;
/**
* Close the data store.
*/
public void close() throws SDataStoreException;
}
There is also a factory for data stores:
public interface ISDataStoreFactory {
/**
* #param dataStoreId id of the data store
* #return ISDataStore with given id. Type of this id depends on target platform
*/
public ISDataStore getDataStore(Object dataStoreId) throws SDataStoreException;
/**
* Destroys data store with given id.
* #param dataStoreId id of the data store. Type of this id depends on target platform
*/
public void destroyDataStore(Object dataStoreId) throws SDataStoreException;
}
Docs auto-generated by Doxygen can be found here.
Mercurial repository with Interface and all the implementations can be found here.
How do I use it:
As I already said in my question, I have app for Android and app for J2ME, both these apps does the similar thing. (if anyone interested, they does communication via bluetooth with remote embedded device)
Both apps have common low-level part that does the main job.
I have interface IMainApp, something like that:
public interface IMainApp {
public ISDataStoreFactory getDataStoreFactory();
/*
* ... some other methods
*/
}
Both apps (for Android and for J2ME) have its own implementations of this interface, and they pass its reference to the low-level part. When low-level part wants to open some data store, it uses ISDataStoreFactory returned by IMainApp.getDataStoreFactory. It works just like I want it to work.
Hope it is useful for anyone.
Am shou you what i did
create profiles .. that are values i want to store in the database
Sample profile
public class NewsProfile {
public String uniqid = "", category = "", title = "" ;
public NewsProfile(String uniqid) {
this.uniqid = uniqid;
}
}
Create a News store that accept New Profile
public void saveProfile(int id, NewsProfile profile) {
try {
if (rs != null) {
profile.id = id;
byte[] bytes = toByteArray(profile);
setRecord(profile.id, bytes);
System.err.println("Exists = " + profile.catKey + String.valueOf(profile.status));
}
} catch (Exception e) {
System.err.println("ERROR: saveUpdateProfile" + e.getMessage());
}
}
public NewsProfile getProfileint id) throws RecordStoreException, IOException {
byte[] bytes = rs.getRecord(id);
DataInputStream is = new DataInputStream(new ByteArrayInputStream(bytes));
String uniqid = is.readUTF();
OptionsProfile profile = new NewsProfile (uniqid);
profile.id = id;
profile.catKey = uniqid;
profile.category = is.readUTF();
profile.title = is.readUTF();
return profile;
}
private byte[] toByteArray(NewsProfile profile) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream os = new DataOutputStream(baos);
os.writeUTF(profile.uniqid);
os.writeUTF(profile.category);
os.writeUTF(profile.title);
return baos.toByteArray();
}
What this means is that anytime i want to save data to a database .... what am saving at any point in time is NewsProfile .... You can not implement for different storage you want .. SQLite , RMS , even Web Service
Thanks
:)