I'm currently using Scribe to both authenticate and post non-media messages to Twitter successfully. This was very easy, my first test message posted with no issues. However, I can't seem to post photos at all. I have reviewed Twitter's instructions for posting with media, both here and here.
All of the Scribe/Twitter examples at Github are for non-media posts. It would be great if someone could provide a solid example of how to post photos to Twitter via Scribe!
I'm have two issues in particular:
1) My posts will not pass authorization. I've tried mimicking the examples I posted above, but nothing seems to work.
2) When converting the image from byte[] to a string, I only seem to get 4113 characters before it stops. From my understanding, this is well under the number of characters a String can hold.
Here is how I'm extracting the photo:
// GET PHOTO FILE AND FILE LENGTH
// INSTANTIATE UPLOAD VARIABLE WITH FILE LENGTH
File file = new File(photo); // ("photo" is a string path to the photo file)
int fileLength = (int) file.length();
uploadFile = new byte[fileLength];
// CREATE BUFFER INPUT STREAM OF FILE
BufferedInputStream inputStream;
try {inputStream = new BufferedInputStream(new FileInputStream(file));}
catch (FileNotFoundException e)
{
inputStream = null;
Toast.makeText(this.getApplicationContext(), "Buffer input stream error!", Toast.LENGTH_LONG).show();
}
// READ DATA FROM FILE INTO UPLOAD VARIABLE
// CLOSE INPUT STREAM
try {inputStream.read(uploadFile);}
catch (IOException e) {Toast.makeText(this.getApplicationContext(), "Read input stream to upload variable error!", Toast.LENGTH_LONG).show();}
try {inputStream.close();}
catch (IOException e) {Toast.makeText(this.getApplicationContext(), "Close input stream error!", Toast.LENGTH_LONG).show();}
After a LOT of research and piece milling code from various places I finally figured out what I was doing wrong. Here is an example of how to post photos to Twitter via Scribe OAuth:
NOTE: This assumes a few things...
1) You have already saved the photo and have the file path
2) You have already authenticated the user at some point and have a valid access Token
3) You MUST add apache-mime4j-0.6.jar & httpmime-4.0.1.jar to you libs folder and include them in your build path!!!
I really hope this helps someone! It's very easy to implement, but took a few days of troubleshooting to get it working correctly!
// BUILD OAUTH SERVICE
OAuthService oAuth = new ServiceBuilder()
.provider(TwitterApi.class)
.apiKey(YOUR_TWITTER_API_KEY) // REPLACE WITH YOUR OWN!!!
.apiSecret(YOUR_TWITTER_API_SECRET) // REPLACE WITH YOUR OWN!!!
.callback(YOUR_CALLBACK) // REPLACE WITH YOUR OWN!!!
.build();
// BUILD OAUTH REQUEST & SIGN IT RIGHT AWAY (OTHERWISE MULTIPART FORM MAY PREVENT SIGNING)
OAuthRequest request = new OAuthRequest(Verb.POST, "https://upload.twitter.com/1.1/statuses/update_with_media.json");
oAuth.signRequest(USER_ACCESS_TOKEN, request); // ENTER USER'S ACCESS TOKEN
// ADD MULTIPART FORM
try
{
MultipartEntity entity = new MultipartEntity();
entity.addPart("status", new StringBody(message)); // THIS IS THE TWITTER MESSAGE
entity.addPart("media", new FileBody(new File(photo))); // THIS IS THE PHOTO TO UPLOAD
ByteArrayOutputStream out = new ByteArrayOutputStream();
entity.writeTo(out);
request.addPayload(out.toByteArray());
request.addHeader(entity.getContentType().getName(), entity.getContentType().getValue());
}
catch (UnsupportedEncodingException e) {e.printStackTrace();}
catch (IOException e) {e.printStackTrace();}
// SEND REQUEST
try {response = new JSONObject (request.send().getBody());}
catch (JSONException e) {Log.e("YOUR_APP_TAG", "JSONException Thrown: " + e.getMessage());}
Related
I have an android app that loads images and text files into Dropbox. I've figured out the authentication and upload process.
Now, using the same authenticated session, I want to read one of the uploaded text files (to look for changes). I've found a download example, but that would mean writing it to local SD, then reading for there ... not efficient at all (in part because of the additional android permission required).
I've examined Dropbox's v2 documentation and there do seem to be a bunch of read calls but I can't, for the life of me, figure out how to use them. The helpful Android-Dropbox examples also don't seem to tackle my specific problem. I couldn't find any v2 examples on stackoverflow either.
Surely, somebody can point me to a simple example that provides a nice InputStream.
You can use the Dropbox Java SDK download method to get file contents directly. There's an example of using that in the example app here. That example writes directly to a FileOutputStream.
It sounds like you just want an InputStream though, which would look like this:
DbxClientV2 client = new DbxClientV2(config, ACCESS_TOKEN);
String remotePath = "/test.txt"; // the path to the file you want to download
InputStream fileInputStream = null;
try {
fileInputStream = client.files().download(remotePath).getInputStream();
// use `fileInputStream` as desired
} catch (DbxException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
After much tooling around, here's something that works
String my_link = null;
URL my_url = null;
URLConnection conn = null;
BufferedReader reader = null;
try {
my_link = my_DbxClient.files().getTemporaryLink("/" + my_File).getLink();
my_url = new URL (my_link);
conn = my_url.openConnection();
reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
} catch (DbxException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
I'm trying to copy url contents with user info.
First, the user log in and then the page show the user info. I want to copy that info to a String.
I am using this:
try {
variable1 = new Scanner(new URL("https://example.com/hello").openStream(), "UTF-8").useDelimiter("\\A").next();
}catch (MalformedURLException e) {
System.out.println("The URL is not valid.");
}catch (IOException e) {
System.out.println("The URL is not valid.");
}
But I am getting the content in the login page...(as the user never logged in).
I thing maybe missing the cookie id in the request header. The cookie id is in the header of the response after the login request finished.
I am working on an android application that needs to print to a printer. I decided on using the Google Cloud Print, as it seemed easy to set up. Initially, I followed the steps found here for integrating into Android. This works, as in it will print to my desired printer. However, this process is a bit involved for the user. In my case, the process is as follows:
The user selects the print button that I have displayed next to some information.
A Dialog is shown with a preview of what will be printed. There is a button in the ActionBar that says "Print". This begins the process.
A new Activity is displayed showing a list of printers that are connected to that users Google Account. The user must select one.
A new page is shown giving a description of the print job.
The user has to select "Print" in the upper right hand corner.
The print job is started and the printer prints out the picture.
Unfortunately, my client does not want this process. They want the user to click "Print" in step two, and then have the picture printed (steps 1, 2 and 6). Thus, I cannot use Intent provided by Google, I must use the actual API. This requires me to get a Google Auth token, get the desired printer, and submit a print job that way. I do the following:
Use the Google Play Services to retrieve an OAuth token for the users Gmail account.
Get a list of printers using the /search API call.
Submit a print job using the /submit API call.
I have the first two finished. I am just having trouble with the actual printing of the picture. Instead of printing the picture, the byte data of the picture is being printed (Base64 encoded). Here is some code as to how I am sending up the request:
ContentResolver contentResolver = context.getContentResolver();
try {
InputStream is = contentResolver.openInputStream(uri);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
int n = is.read(buffer);
while (n >= 0) {
baos.write(buffer, 0, n);
n = is.read(buffer);
}
is.close();
baos.flush();
content = Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT);
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + uri.toString(), e);
} catch (IOException e) {
e.printStackTrace();
}
This code retrieves the picture (the variable "uri" is the URI of that file), and turns it into a Base64 encoded string. This is the same method used in the PrintDialogActivity that is provided on the Google Cloud Print page (linked to above). The following is how I send that up:
URL: http://www.google.com/cloudprint/submit?access_token=[AUTH_TOKEN_GOES_HERE]&cookies=false&printerid=[PRINTER_ID_HERE]
HTTP Method: POST
POST Parameters: [printerId=PRINTER_ID_HERE, title=TestPrint, contentType=image/jpeg, capabilities={"capabilities":[{}]}, content=[Base64 Encoded data string is placed here]]
As far as I can tell, this is how it is supposed to be. I am getting a response of {"success":true} when printing. But, as I said above, it prints out the actual Base64 data string. Any help would be appreciated.
EDIT: Using what powerje said below, I managed to fix this. Rather than using the code above, I used the following:
public void submitPrintJobWithFile(String printerId, String title, String token, String filePath, String contentType){
File file = new File(filePath);
// Method that gets the correct headers
List<Header> headers = getHeaders(contentType, token);
// Method that gets the correct post parameters
String url = CLOUDPRINT_URL + PATH_SUBMIT;
List<NameValuePair> postParams = getParams(title, contentType);
String params = "access_token=" + token + "&cookies=false" + "&printerid=" + printerId;
url += params;
response = sendMultipartData(url, file, postParams, headers);
}
private String sendMultipartData(String url, File file, List<NameValuePair> fields, List<Header> headers){
HttpPost post = new HttpPost(url);
MultipartEntity entity = new MultipartEntity();
for(NameValuePair pair : fields){
String name = pair.getName();
String value = pair.getValue();
try{
entity.addPart(name, new StringBody(value));
}catch (UnsupportedEncodingException e){
Log.d(TAG, "Error turning pair (name=" + name + ", value=" + value + ") into StringBody.");
}
entity.addPart("content", new FileBody(file));
post.setEntity(entity);
// Finish HttpClient request here...
}
It looks like you need to use multipart encoding, example here:
http://blog.tacticalnuclearstrike.com/2010/01/using-multipartentity-in-android-applications/
FTA:
The files needed are apache-mime4j, httpclient, httpcore and httpmime. All are opensource projects built by the Apache foundation.
Download the 4 files and add them to your project then you should be able to use the following code to post strings and files to pages.
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://www.tumblr.com/api/write");
try {
MultipartEntity entity = new MultipartEntity();
entity.addPart("type", new StringBody("photo"));
entity.addPart("data", new FileBody(image));
httppost.setEntity(entity);
HttpResponse response = httpclient.execute(httppost);
} catch (ClientProtocolException e) {
} catch (IOException e) {
}
The image variable in this case is a File that contains an image captured by the camera on the phone.
Looking at the Python Sample Code SubmitJob method it seems that only the PDF typs needs to be encoded in Base64.
Answering the question with a bit of an update. As of October 2013, in 4.4 and the support library, there are built in methods to handle printing. See the following documentation for how to do it properly:
PrintHelper - The support Library class to help with printing Bitmaps.
DevBytes: Android 4.4 Printing API - An Android Developers video detailing the APIs
Printing Content - An Android Training guide on how to use these APIs.
I am trying to upload media to twitter in android. I am using this Update with Media Api. I am using the following code
multiPartEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
try
{
multiPartEntity.addPart("status", new StringBody("Metallica rules man! |m|"));
multiPartEntity.addPart("media[]", new InputStreamBody(getResources().openRawResource(R.drawable.metallica), "metallica.jpg"));
post = new HttpPost("https://api.twitter.com/1.1/statuses/update_with_media.json");
post.setEntity(multiPartEntity);
post.addHeader("Content-Type", "multipart/form-data");
post.getParams().setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, false);
consumer.sign(post);
response = client.execute(post);
entity = response.getEntity();
} catch (Exception e1)
{
e1.printStackTrace();
}
But I get the error code 131 - Internal error from Twitter. I also tried sending the image in the form of a byte array but in vain. I got the same error. Could anyone please help me in resolving this issue?
I am working in Windows 7, and I am learning to code for Android.
I need to create an FTP client to upload and download the files from free FTP servers. I am using "www.drivehq.com", which is a free ftp space. I need to know whether I can use this kind of free space as my FTP server, or if not, which FTP server can be used?
I have written the following code to login to an FTP server, as well as to upload a file. It doesnt show any errors, but I couldn't check from the emulator (android 2.2) whether the login was successful. The file is not uploaded, I separately checked through website using my login account in that FTP server.
How should I proceed further? How can I login successfully and upload the file?
FTPClient con = new FTPClient();
try
{
con.connect("http://www.ftpserver.com");
if (con.login("user name", "password"))
{
con.enterLocalPassiveMode(); // important!
String data = "test data";
ByteArrayInputStream in = new ByteArrayInputStream(data.getBytes());
boolean result = con.storeFile("/sdcard/abc.jpg", in);
in.close();
if (result) Log.v("upload result", "succeeded");
//lblResult.setText("Login successful.");
}
}
catch (Exception e)
{
e.printStackTrace();
}
try
{
con.logout();
con.disconnect();
}
catch (IOException e)
{
e.printStackTrace();
}
lblResult.setText("Login successful.");
else {
lblResult.setText("Login failed. Username and/or password doesn't match.");
}
}
});
i dont know, whether i am getting any exception.
FTPClient con = new FTPClient();
try
{
con.connect("FTPserver");
if (con.login("username", "password"))
{
lblResult.setText("Login successful.");
con.enterLocalPassiveMode();
i have changed
con.connect("http://www.ftpserver.com");
into
con.connect("ftp.ftpserver.com");
when i run this it prints "login successful", it means, i have logged in, isn't it? but file is not getting uploaded.
String data = "test data";
ByteArrayInputStream in = new ByteArrayInputStream(data.getBytes());
boolean result = con.storeFile("/text.txt", in);
what is this test data?
"con.storefile"- inside the brackets what i need to fill? whether destination location or path of the source file need to be uploaded.
if it is the path of source file, i have my datas in the sdcard,which i have created virtually for my emulator, using DDMS perspective i loaded the files in sdcard, how can i represent the path of that file, if it is destination location, should i need to include the url of the directory?
You can check this link http://www.javaworld.com/javaworld/jw-04-2003/jw-0404-ftp.html.
It says:
URL url = new URL("ftp://user01:pass1234#ftp.foo.com/README.txt;type=i");
URLConnection urlc = url.openConnection();
InputStream is = urlc.getInputStream(); // To download
OutputStream os = urlc.getOutputStream(); // To upload