Jersey Client + Multipart form data + MessageBodyWriter issue - android

I'm having an issue with a Multipart-form-data POST request using the Jersey Client API on Android. I've been following various examples on the web and they are all fairly similar in regards to the implementation.
Client client = createClientInstance();
WebResource r = client.resource(BASEURL).path("DataUpload");
ClientResponse post;
try {
FormDataMultiPart multiPart = new FormDataMultiPart();
multiPart.field("account", account);
multiPart.field("checksum", checksum);
multiPart.bodyPart(new FileDataBodyPart("file", file, MediaType.APPLICATION_OCTET_STREAM_TYPE));
post = r.type(MediaType.MULTIPART_FORM_DATA)
.accept(MediaType.TEXT_PLAIN)
.post(ClientResponse.class, multiPart);
} catch (ClientHandlerException e) {
Log.e(TAG, e.getLocalizedMessage());
} finally {
client.destroy();
}
When I execute this code on my device, I am presented with an exception:
javax.ws.rs.WebApplicationException: java.lang.IllegalArgumentException: No MessageBodyWriter for body part of type 'java.io.File' and media type 'application/octet-stream'
I thought Jersey was supposed to handle File objects without any extra configuration. Removing the bodypart line will allow Jersey to make the request but that eliminates the point of this.
I have these libraries on my buildpath (which were pulled in with Maven):
jersey-client-1.14
jersey-core-1.14
jersey-multipart-1.14
mimepull-1-6

I can suggest two things to try:
remove the MIME type from the FileDataBodyPart construction to see if Jersey can find a mime type it is happy to default to :
multiPart.bodyPart(new FileDataBodyPart("file", file, MediaType.APPLICATION_OCTET_STREAM_TYPE));
tell your client config about the multipart body writer (presumably inside your createClientInstance() method) :
com.sun.jersey.api.client.config.ClientConfig config = new com.sun.jersey.api.client.config.DefaultClientConfig();
config.getClasses().add(MultiPartWriter.class);
client = Client.create(config);
Hope that helps.

Related

Sendgrid Android plugin init error "java.lang.NoSuchFieldError: No static field INSTANCE of type .../AllowAllHostnameVerifier"

I'm trying the Sendgrid plugin API for Android. I'm following the step on Sendgrid website, which ends with:
import com.sendgrid.*;
import java.io.IOException;
public class Example {
public static void main(String[] args) throws IOException {
Email from = new Email("test#example.com");
String subject = "Sending with SendGrid is Fun";
Email to = new Email("test#example.com");
Content content = new Content("text/plain", "and easy to do anywhere, even with Java");
Mail mail = new Mail(from, subject, to, content);
SendGrid sg = new SendGrid(System.getenv("SENDGRID_API_KEY"));
Request request = new Request();
try {
request.setMethod(Method.POST);
request.setEndpoint("mail/send");
request.setBody(mail.build());
Response response = sg.api(request);
System.out.println(response.getStatusCode());
System.out.println(response.getBody());
System.out.println(response.getHeaders());
} catch (IOException ex) {
throw ex;
}
}
}
This code produce error on:
SendGrid sg = new SendGrid(System.getenv("SENDGRID_API_KEY"));
of:
java.lang.NoSuchFieldError: No static field INSTANCE of type Lorg/apache/http/conn/ssl/AllowAllHostnameVerifier; in class Lorg/apache/http/conn/ssl/AllowAllHostnameVerifier; or its superclasses (declaration of 'org.apache.http.conn.ssl.AllowAllHostnameVerifier' appears in /system/framework/framework.jar!classes3.dex)
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.<clinit>(SSLConnectionSocketFactory.java:144)
at org.apache.http.impl.client.HttpClientBuilder.build(HttpClientBuilder.java:966)
at org.apache.http.impl.client.HttpClients.createDefault(HttpClients.java:58)
at com.sendgrid.Client.<init>(Client.java:56)
at com.sendgrid.SendGrid.<init>(SendGrid.java:52)
...
From other answer, I discovered that AllowAllHostnameVerifier has been deprecated since API v22. But I don't have enough knowledge in Android to be able to toying around with third party library and change it into HTTPUrlConnection.
I also stumble upon this sendgrid library that change that particular networking library to Http library, but when I tried to run, I got tons of "duplicate class" error between httpclient-android-4.3.5.1.jar (org.apache.httpcomponents:httpclient-android:4.3.5.1) and httpcore-4.3.2.jar (org.apache.httpcomponents:httpcore:4.3.2).
How can I resolve or work around this problem? I have used the latest Sendgrid plugins (4.4.1), and the same problem still popped up.

Supporting cookies in Google Exoplayer

I am setting a HttpCookie in my android application associated with a domain within the cookieManager. Then, when I stream HLS videos using exo player, I want this cookie to used for each of the .ts chunk requests.
This is the code, I use to store the cookie in the Application section of the project:
String url1 = "http://sdtest.vzvisp.com";
URI auri1 = null;
try {
auri1 = new URI(url1);
} catch (URISyntaxException e) {
e.printStackTrace();
}
AppGlobal.cookieManager = new CookieManager(null, CookiePolicy.ACCEPT_ALL);
AppGlobal.cookieManager.getCookieStore().add(auri1, new HttpCookie("JSESSIONID","aaaMp0uKke4gp"));
AppGlobal.cookieManager.getCookieStore().add(auri1,new HttpCookie("JSESSIONID1","aaaMp0uKke4gasasasp"));
AppGlobal.currentHandler = CookieHandler.getDefault();
if (AppGlobal.currentHandler != AppGlobal.cookieManager) {
CookieHandler.setDefault(AppGlobal.cookieManager);
}
This is an example of a chunk request sent :
http://sdtest.vzvisp.com:22779/AppConfig/SIT/fios/hls/fios/fios_hls_1m_00004.ts?vzSvc=fU2h73FMzhPgj8w0VNqYYsQ3lVZq8jjIWr6Xfrmraq4=&vispVzKey=54038752&vispIconFg=1&vispUsr=ZPq5BrbWoSQm1nsCNTPfBA==&vispAuthSid=CIAAASAIuwE&vispExpTime=1481081538&vispAuthKey=36958733&vispAuthSign=7.23.GMoCIpxmT_k123kT3P8iJxmCF-BWmeiAXQontU11hUI
But, when I inspect the packet, I do not see the cookie sent. Can someone kindly help me out ?
Thanks.
Try doing something like this:
AppGlobal.cookieManager.setCookie("http://sdtest.vzvisp.com","JSESSIONID=aaaMp0uKke4gp; Domain=.vzvisp.com; Path=/; Version=1");
Check this ticket to see how to set hls cookie correctly:
Hope this help

Serve mp3 stream for android with Laravel

Here's my problem: I'm writing a laravel backend which have to serve an mp3 file that had to be reproduced by using the android standard media player.
For the laravel backend I need to use JWT to handle authentication so on every request headers I have to set the "Authorization" field to "Bearer {token}" .The laravel route is "/songs/{id}" and is handled in this way:
public function getSong(Song $song) {
$file = new File(storage_path()."/songs/".$song->path.".mp3");
$headers = array();
$headers['Content-Type'] = 'audio/mpeg, audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3';
$headers['Content-Length'] = $file->getSize();
$headers['Content-Transfer-Encoding'] = 'binary';
$headers['Accept-Range'] = 'bytes';
$headers['Cache-Control'] = 'must-revalidate, post-check=0, pre-check=0';
$headers['Connection'] = 'Keep-Alive';
$headers['Content-Disposition'] = 'attachment; filename="'.$song->path.'.mp3"';
$user = \Auth::user();
if($user->activated_at) {
return Response::download($file, $song->path, $headers);
}
\App::abort(400);
}
On the android side I'm using the MediaPlayer to stream the mp3 file in this way:
media_player = new MediaPlayer();
try {
media_player.setAudioStreamType(AudioManager.STREAM_MUSIC);
String token = getSharedPreferences("p_shared", MODE_PRIVATE).getString("token", null);
Map<String, String> headers = new HashMap<>();
headers.put("Authorization", "Bearer " + token);
media_player.setDataSource(
getApplicationContext(),
Uri.parse(ConnectionHelper.SERVER + "/songs/" + song.getId()),
headers
);
} catch (IOException e) {
finish();
Toast.makeText(
Round.this,
"Some error occurred. Retry in some minutes.",
Toast.LENGTH_SHORT
).show();
}
media_player.setOnCompletionListener(this);
media_player.setOnErrorListener(this);
media_player.setOnPreparedListener(this);
But every time I execute the code I get extra code -1005 on the error listener that means ERROR_CONNECTION_LOST.
The problem: Response::download(...) doesn't produce a stream, so I can't serve my .mp3 file.
The solution:
As Symfony HttpFoundation doc. says in the serving file paragraph:
"if you are serving a static file, you can use a BinaryFileResponse"
The .mp3 files I need to serve are statics in the server and stored in "/storage/songs/" so I decided to use the BinaryFileResponse, and the method for serving .mp3 became:
use Symfony\Component\HttpFoundation\BinaryFileResponse;
[...]
public function getSong(Song $song) {
$path = storage_path().DIRECTORY_SEPARATOR."songs".DIRECTORY_SEPARATOR.$song->path.".mp3");
$user = \Auth::user();
if($user->activated_at) {
$response = new BinaryFileResponse($path);
BinaryFileResponse::trustXSendfileTypeHeader();
return $response;
}
\App::abort(400);
}
The BinaryFileResponse automatically handle the requests and allow you to serve the file entirely (by making just one request with Http 200 code) or splitted for slower connection (more requests with Http 206 code and one final request with 200 code).
If you have the mod_xsendfile you can use (to make streaming faster) by adding:
BinaryFileResponse::trustXSendfileTypeHeader();
The android code doesn't need to change in order to stream the file.

About how to pass the ParseObject(Object) using Rest API(service) in Installation class in android?

I am sagar, i am trying to implement the Parse Push-Notification in android using REST API (Service), and i am almost got success in implement the Push-Notification in Xamarin-Android using REST API. But i got stuck with one part in sending the Data into REST service. I trying to pass the ParseObject in service, but the in parse table there is a need of Object,(). I have tried to pass the ParseObject as below:
JsonConvert.SerializeObject(ParseUser.CurrentUser)
It convert ParseObject into array and array is not accepted in table and ,i got failed to save it in table. because there i a need of object.
I need solution or suggestion from developer guys. Yours help will be appreciated. I am trying the below code to achieve the result.
public static void RegisterPush(string regristrationId)
{
if (regristrationId != null) {
string appID = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
string restID = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
string masterID = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
try {
var client = new RestClient ("https://api.parse.com");
var request = new RestRequest ("1/installations", RestSharp.Method.POST);
request.AddHeader ("Accept", "application/json");
request.AddHeader ("X-Parse-Application-Id", appID);
request.AddHeader ("X-Parse-REST-API-Key", restID);
request.Credentials = new NetworkCredential (appID, masterID);
request.Parameters.Clear ();
Console.Error.WriteLine ("ParseUser.CurrentUser-->"+ (ParseObject) ParseUser.CurrentUser);
//JsonConvert.SerializeObject(ParseUser.CurrentUser)
string strJSONContent = "{\"user\" :"+ JsonConvert.SerializeObject(ParseUser.CurrentUser)+",\"owner\":\"" + ParseUser.CurrentUser.ObjectId + "\",\"deviceType\":\"android\",\"GCMSenderId\":\"1234567890\",\"appName\":\"abcdefgh\",\"pushType\":\"gcm\",\"deviceToken\":\"" + regristrationId + "\"}";
Console.Error.WriteLine("json string-->"+ strJSONContent);
request.AddParameter ("application/json", strJSONContent, ParameterType.RequestBody);
client.ExecuteAsync (request, response => {
Console.Error.WriteLine ("response for android parse installation-->" + response.Content);
});
} catch (Exception ex) {
Console.WriteLine (ex.Message);
}
}
}`
Output:{"user" :[{"Key":"dealOffered","Value":4},{"Key":"dealRequested","Value":5},{"Key":"displayName","Value":"Cook"},{"Key":"email","Value":"lorenzo#gmail.com"},{"Key":"firstName","Value":"Lorenzo"},{"Key":"lastName","Value":"Cook"},{"Key":"mobileNumber","Value":9999999999.0},{"Key":"picture","Value":{"IsDirty":false,"Name":"tfss-afd25c29-6679-4843-842c-fe01f7fcf976-profile.jpg","MimeType":"image/jpeg","Url":"http://files.parsetfss.com/profile.jpg"}},{"Key":"provider","Value":"password"},{"Key":"userType","Value":"Merchant"},{"Key":"username","Value":"merchant#sailfish.com"},{"Key":"zipCode","Value":2342343}],"owner":"3cF1vHUXkW","deviceType":"android","GCMSenderId":"1234567890123","appName":"Sailfish","pushType":"gcm","deviceToken":"APA91bE3bsTIInQcoloOBE4kdLVVHVTRVtNyA1A788hYSC15wAVu8mUg-lwk7ZPk370rngrK7J6OoLmiM9HRr1CGPaBo6LCNrSUL7erBku4vepaFFkQzgqS6BcAemp"}
Error:{"code":111,"error":"invalid type for key user, expected *_User, but got array"}
maven
I found the solution in , parse xamarin docs, in one query , the way is simple, but i little bit hard to found out.
The issue is with the data passing in json format in REST, to pass any pointer using REST API, use as below.
The solution is as below:
`{
"user":{
"__type":"Pointer",
"className":"_User",
"objectId":"qYvzFzGAzc"
},
"owner":"qYvzFzGAzc",
"deviceType":"android",
"GCMSenderId":"123456789",
"appName":"NiceApp",
"pushType":"gcm",
"deviceToken":"APA91bFeM10jdrCS6fHqGGSkON17UjEJEfvJEmGpRM-d6hq3hQgDxKHbyrqAIxMnEGgbLEZf0E9AllHxiQQQCdEFiNMF1_A8q0n9tGpBE5NKhvS2ZGJ9PZ7585puWqz_1Z1EjSjOvgZ1LQo708DeL2KzA7EFJmdPAA"
}`
It looks like your column user is set up wrong. It should show as a Pointer<_User> not Pointer
If you load this class in your Data Browser, is the "user" key defined as a string, or a Pointer <_User>
This error seems to indicate that this is a string column, which is why the Parse.User object is not being accepted as a valid value. You might have tried setting a string on this key before, which in turn type-locked the "user" key as a string column.
Found it on the examples given on this page - https://www.parse.com/docs/rest
Have you check your REST API connection while passing ParseObject?
Because your error says:
Error:{"code":111,"error":"invalid type for key user, expected *_User, but got array"}
Here "code":111This error code comes when server refuse for connection

Smack getPrivacyList method throws classCastException

I am using Smack in an Android app for XMPP based communication. I am trying to create a privacy list using PrivacyManager. I have created a PrivacyList successfully, but when I try to access that list it returns ClassCastException. Here is the code:
PrivacyListManager privacyManager;
privacyManager = PrivacyListManager.getInstanceFor(connection);
PrivacyList privacyList = privacyManager.getPrivacyList("msg_block_list");
Investigating a bit more, I have found that the exception occurs in getRequest method in PrivacyListManager.java class on following line:
Privacy privacyAnswer =
(Privacy) response.nextResult(SmackConfiguration.getPacketReplyTimeout());
Here is the getRequest method:
private Privacy getRequest(Privacy requestPrivacy) throws XMPPException {
// The request is a get iq type
requestPrivacy.setType(Privacy.Type.GET);
requestPrivacy.setFrom(this.getUser());
// Filter packets looking for an answer from the server.
PacketFilter responseFilter = new PacketIDFilter(requestPrivacy.getPacketID());
PacketCollector response = connection.createPacketCollector(responseFilter);
// Send create & join packet.
connection.sendPacket(requestPrivacy);
// Wait up to a certain number of seconds for a reply.
Privacy privacyAnswer =
(Privacy) response.nextResult(SmackConfiguration.getPacketReplyTimeout());
// Stop queuing results
response.cancel();
// Interprete the result and answer the privacy only if it is valid
if (privacyAnswer == null) {
throw new XMPPException("No response from server.");
}
else if (privacyAnswer.getError() != null) {
throw new XMPPException(privacyAnswer.getError());
}
return privacyAnswer;
}
I have followed this tutorial for implementing PrivacyList. Anyone can help?
PacketCollector's method getResult() returns Packet object, but it could be any inherited from Packet class object, either Message or Presence or IQ (in IQ case you can use (privacy) cast, because Privacy is IQ's child class). In your case it seems like you get object which is present in another hierarchy, than Privacy class.
I have found the problem. The XML file smack.providers was missing. I created the file with following contents and it worked.
<?xml version="1.0"?>
<!-- Providers file for default Smack extensions -->
<smackProviders>
<!-- Privacy -->
<iqProvider>
<elementName>query</elementName>
<namespace>jabber:iq:privacy</namespace>
<className>org.jivesoftware.smack.provider.PrivacyProvider</className>
</iqProvider>
</smackProviders>

Categories

Resources