Android Retrofit Request Using AWS Signature Authorization - android

I'm trying to get data from the API which needs to handle aws-authentication, my question is how can I generate Authorization and X-Amz-Date?
I have to pass 3 parameter as header: Content-Type, Authorization and X-Amz-Date.
As you can find in image:
here is the function that generate Authorization String:
public static String gerateOAuthAWS(Context co) throws Exception {
JodaTimeAndroid.init(co);
DateTimeFormatter fmt = DateTimeFormat.forPattern("EEE', 'dd' 'MMM' 'yyyy' 'HH:mm:ss' 'Z").withLocale(Locale.US);
String ZONE = "GMT";
DateTime dt = new DateTime();
DateTime dtLondon = dt.withZone(DateTimeZone.forID(ZONE)).plusHours(1);
String formattedDate = dtLondon.toString(fmt);
String oauth = "AWS4-HMAC-SHA256 Credential="+ ACCESS_KEY+"/us-east-1/execute-api/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature="+
getSignatureKey(SECRET_KEY,formattedDate,"us-east-1","execute-api");
return oauth;
}
static byte[] HmacSHA256(String data, byte[] key) throws Exception {
String algorithm="HmacSHA256";
Mac mac = Mac.getInstance(algorithm);
mac.init(new SecretKeySpec(key, algorithm));
return mac.doFinal(data.getBytes("UTF8"));
}
static String getSignatureKey(String key, String dateStamp, String regionName, String serviceName) throws Exception {
byte[] kSecret = ("AWS4" + key).getBytes("UTF8");
byte[] kDate = HmacSHA256(dateStamp, kSecret);
byte[] kRegion = HmacSHA256(regionName, kDate);
byte[] kService = HmacSHA256(serviceName, kRegion);
byte[] kSigning = HmacSHA256("aws4_request", kService);
return Base64.encodeToString(kSigning,Base64.DEFAULT).replaceAll("\n", "");
}
Content-Type is "application/x-www-form-urlencoded"
and generate X-Amz-Date something as: "201805138T120046Z"
then pass them through retrofit methods:
#GET("prod/video")
Call<ArrayList<Video>> getAllVideos(#Header("Content-Type")String content_type,
#Header("X-Amz-Date")String amz_date,
#Header("Authorization")String auth);
the result returns null and I'm sure the issue is related the authorization since it worked before well.
thanks for your helps :)

i always said to my friends why do you use retrofit or valley , if it's seems complicated to you !
instead you can use JSOUP or OKHTTP it's much easier and I realy love JSOUP
an example that you can connect and send you data:
private void fcmIdentity(final String fcmKey) {
new Thread(new Runnable() {
#Override
public void run() {
try {
SSLHelper.enableSSLSocket();
Connection.Response response = Jsoup
.connect(Urls.identity)
.header("Accept", "application/json")
.header("KEY_2", "VALUE_2")
.method(Connection.Method.POST)
.ignoreContentType(true)
.ignoreHttpErrors(true)
.validateTLSCertificates(true)
.followRedirects(true)
.data("fcm", "" + fcmKey)
.data("identity", preferences.getString("FCM_ID", ""))
.execute();
Log.i("fcmIdentity", response.statusCode() + "");
Log.i("fcmIdentity", response.toString());
Log.d("fcmIdentity", response.headers().toString());
Log.i("fcmIdentity", response.body());
} catch (Exception e) {
e.printStackTrace();
if (e instanceof IOException) {
G.toast(getString(R.string.connection_error), true);
}
}
}
}).start();
}
about SSLHelper it help to connect to HTTPS
for more info check my topic https://answers.uncox.com/android/question/13003

Related

UnityWebRequest uploadProgress [duplicate]

How can I send HTTP GET and POST requests in C# with Unity?
What I want is:
send json data in post request (I use Unity serializer, so no need in
new one, I just want to pass string in post data and have ability to
set ContentType to application/json);
get response code and body without any problems;
do it all asynchronous without blocking ui rendering.
What I've tried:
implementing with HttpWebRequest/HttpWebResponse, but it's too hard and low level (if I won't found anything better, I'll have to use it);
using unity WWW, but it doesn't match my requirements;
using some external packages from NuGet - Unity don't accept them :(
Most problems were with threading, I'm not experienced enough in it in C#.
IDE, I use, is Intellij Rider.
The WWW API should get this done but UnityWebRequest replaced it so I will answer the newer API. It's really simple. You have to use coroutine to do this with Unity's API otherwise you have have to use one of C# standard web request API and Thread. With coroutine you can yield the request until it is done. This will not block the main Thread or prevent other scripts from running.
Note:
For the examples below, if you are using anything below Unity 2017.2, replace SendWebRequest() with Send() and then replace isNetworkError with isError. This will then work for the lower version of Unity. Also, if you need to access the downloaded data in a binary form instead, replace uwr.downloadHandler.text with uwr.downloadHandler.data. Finally, the SetRequestHeader function is used to set the header of the request.
GET request:
void Start()
{
StartCoroutine(getRequest("http:///www.yoururl.com"));
}
IEnumerator getRequest(string uri)
{
UnityWebRequest uwr = UnityWebRequest.Get(uri);
yield return uwr.SendWebRequest();
if (uwr.isNetworkError)
{
Debug.Log("Error While Sending: " + uwr.error);
}
else
{
Debug.Log("Received: " + uwr.downloadHandler.text);
}
}
POST request with Form:
void Start()
{
StartCoroutine(postRequest("http:///www.yoururl.com"));
}
IEnumerator postRequest(string url)
{
WWWForm form = new WWWForm();
form.AddField("myField", "myData");
form.AddField("Game Name", "Mario Kart");
UnityWebRequest uwr = UnityWebRequest.Post(url, form);
yield return uwr.SendWebRequest();
if (uwr.isNetworkError)
{
Debug.Log("Error While Sending: " + uwr.error);
}
else
{
Debug.Log("Received: " + uwr.downloadHandler.text);
}
}
POST request with Json:
void Start()
{
StartCoroutine(postRequest("http:///www.yoururl.com", "your json"));
}
IEnumerator postRequest(string url, string json)
{
var uwr = new UnityWebRequest(url, "POST");
byte[] jsonToSend = new System.Text.UTF8Encoding().GetBytes(json);
uwr.uploadHandler = (UploadHandler)new UploadHandlerRaw(jsonToSend);
uwr.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
uwr.SetRequestHeader("Content-Type", "application/json");
//Send the request then wait here until it returns
yield return uwr.SendWebRequest();
if (uwr.isNetworkError)
{
Debug.Log("Error While Sending: " + uwr.error);
}
else
{
Debug.Log("Received: " + uwr.downloadHandler.text);
}
}
POST request with Multipart FormData/Multipart Form File:
void Start()
{
StartCoroutine(postRequest("http:///www.yoururl.com"));
}
IEnumerator postRequest(string url)
{
List<IMultipartFormSection> formData = new List<IMultipartFormSection>();
formData.Add(new MultipartFormDataSection("field1=foo&field2=bar"));
formData.Add(new MultipartFormFileSection("my file data", "myfile.txt"));
UnityWebRequest uwr = UnityWebRequest.Post(url, formData);
yield return uwr.SendWebRequest();
if (uwr.isNetworkError)
{
Debug.Log("Error While Sending: " + uwr.error);
}
else
{
Debug.Log("Received: " + uwr.downloadHandler.text);
}
}
PUT request:
void Start()
{
StartCoroutine(putRequest("http:///www.yoururl.com"));
}
IEnumerator putRequest(string url)
{
byte[] dataToPut = System.Text.Encoding.UTF8.GetBytes("Hello, This is a test");
UnityWebRequest uwr = UnityWebRequest.Put(url, dataToPut);
yield return uwr.SendWebRequest();
if (uwr.isNetworkError)
{
Debug.Log("Error While Sending: " + uwr.error);
}
else
{
Debug.Log("Received: " + uwr.downloadHandler.text);
}
}
DELETE request:
void Start()
{
StartCoroutine(deleteRequest("http:///www.yoururl.com"));
}
IEnumerator deleteRequest(string url)
{
UnityWebRequest uwr = UnityWebRequest.Delete(url);
yield return uwr.SendWebRequest();
if (uwr.isNetworkError)
{
Debug.Log("Error While Sending: " + uwr.error);
}
else
{
Debug.Log("Deleted");
}
}
Use HttpClient and something like:
public static HttpContent DoPost(object payload, string subPath)
{
var httpClient = new HttpClient();
HttpClient.BaseAddress = new Uri(Global.BaseUrl);
HttpClient.DefaultRequestHeaders.Clear();
HttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); // if you're using json service
// make request
var response = Global.HttpClient.PostAsJsonAsync(subPath.TrimLeadingSlash(), payload).Result;
// check for error
response.EnsureSuccessStatusCode();
// return result
return response.Content;
}
Payload is an object to be serialized to json. If all requests are going to the same baseUrl, you can set up HttpClient globally, and reuse it here
https://www.patrykgalach.com/2019/04/18/how-to-call-rest-api-in-unity/
Please refer this link cleanest way to play with data
and do not use www instead of use UnityWebRequest
We can use WWW and UnityWebRequest classes to initiate API calls. WWW got obsolete now and Unity recommends using UnityWebRequest over WWW.
void Start() {
string url = "https://retrofit-backend-demo.herokuapp.com/book";
StartCoroutine(GetBooksUsingWWW(url));
StartCoroutine(GetBooksUsingUnityWebRequest(url));
}
IEnumerator GetBooksUsingWWW(string url) {
using (WWW www = new WWW(url)){
yield return www;
Debug.Log(www.text);
JSONNode jsonNode = JSON.Parse(www.text);
string title = jsonNode[0]["title"].ToString();
Debug.Log("Title: " + title);
}
}
IEnumerator GetBooksUsingUnityWebRequest(string url) {
UnityWebRequest www = UnityWebRequest.Get(url);
yield return www.SendWebRequest();
if(www.isNetworkError || www.isHttpError) {
Debug.Log(www.error);
}
else {
Debug.Log(www.downloadHandler.text);
JSONNode jsonNode = JSON.Parse(www.downloadHandler.text);
string title = jsonNode[0]["title"].ToString();
Debug.Log("Title: " + title);
}
}
For demo: https://github.com/codemaker2015/api-interaction-unity3d-demo

Issue with azure cognitive translation services

After getting the following code to work reliably for a month or so, it stopped working reliably a couple of days ago. About half the time it returns a properly translated string and the other half of the time it returns one of the following two messages:
java.io.FileNotFoundException:
https://api.cognitive.microsoft.com/sts/v1.0/issueToken
java.net.UnknownHostException: Unable to resolve host
"api.microsofttranslator.com": No address associated with hostname
The timing of this problem's beginning coincided with the expiration of my free azure cognitive services account however I migrated to a pay-as-you-go account yesterday and the problem continues.
Why is this happening?
static class translateMessageX extends AsyncTask<String, Void, String>
{
//input string array of 3 items
//[0]is the message to be translated
//[1]is the from language i.e. "english"
//[2]is the to language i.e. "spanish"
//[3]"echo" or "received"
String retString;
String inString = null;
String messageType = null;
String URLHolder = ""; //hold the URL here while we are translating the text
#Override
protected String doInBackground(String... params)
{
inString = params[0];
String from = params[1];
String to = params[2];
messageType = params[3];
int urlStart = inString.indexOf("http");
if (!(urlStart == -1))
{
URLHolder = inString.substring(urlStart);
inString = inString.substring(0, urlStart -1);
}
else
{
URLHolder = "";
}
Integer mesChars = params[0].length();
Integer tCharsLeft = GlobalStuff.getTranslationsFromSP();
if (tCharsLeft > 0)
{
if (tCharsLeft < mesChars) //we charge for both 'echo' and 'received' translations
{
GlobalStuff.updateTranslationInventory(tCharsLeft * -1);
}
else
{
GlobalStuff.updateTranslationInventory(mesChars * -1);
}
GlobalStuff.notifyListeners(this, "#uui", "notused", "notused" );
try
{
Language fromLang = GlobalStuff.getLang(from);
Language toLang = GlobalStuff.getLang(to);
//retString = Translate.execute(inString, fromLang, toLang);
//String debugstr = "look at retStr";
String authenticationUrl = "https://api.cognitive.microsoft.com/sts/v1.0/issueToken";
HttpsURLConnection authConn = (HttpsURLConnection) new URL(authenticationUrl).openConnection();
authConn.setRequestMethod("POST");
authConn.setDoOutput(true);
authConn.setRequestProperty("Ocp-Apim-Subscription-Key", GlobalStuff.translateKey);
IOUtils.write("", authConn.getOutputStream(), "UTF-8");
String token = IOUtils.toString(authConn.getInputStream(), "UTF-8");
System.out.println(token);
// Using the access token to build the appid for the request url
String appId = URLEncoder.encode("Bearer "+token, "UTF-8");
String text = URLEncoder.encode(inString, "UTF-8");
String translatorTextApiUrl = String.format("https://api.microsofttranslator.com/v2/http.svc/Translate?appid=%s&text=%s&from=%s&to=%s", appId, text, fromLang, toLang);
HttpsURLConnection translateConn = (HttpsURLConnection) new URL(translatorTextApiUrl).openConnection();
translateConn.setRequestMethod("GET");
translateConn.setRequestProperty("Accept", "application/xml");
retString = IOUtils.toString(translateConn.getInputStream(), "UTF-8");
String debug = "look at retString";
}
catch (Exception e)
{
retString = e.toString();
}
}
else
{
retString = "OUT OF TRANSLATION CREDITS - " + inString;
}
return retString;
}
#Override
protected void onPostExecute(String result)
{
//rest of logic should be here??
String debug = "look at result";
String answer = extractTranslation(result);
.. . . .
Host not found looks like a simple connectivity error. These hosts do exist.
You can void the call to the token service by passing the key in the call to api.microsofttranslator.com directly:
https://cognitive.uservoice.com/knowledgebase/articles/1815385-api-translator-text-speech-using-the-api-key
That fixes one of the host not found problems, but not the other.
I would recommend though to not embed the key in the client application. It is safer to call the translator service from your own proxy service, where the proxy is able to safely identify your client as your client.

org.springframework.web.client.HttpClientErrorException: 415 Unsupported Media Type[EDITED]

In Android web service using POST method of REST TEMPLATE, I am trying to send an object to server which contains few parameters and and 2 Objects. Those 2 Objects contains few parameters and 3 Lists of different Objects and each of those 3 Lists of Objects contains few parameters inside them and 1 List of Object that contains a byte array alone. Like in the below pics:
Pic 1[Main Object(The one I am trying to send)]:
Pic 2[Object inside the Main Object comprising 3 Lists of Objects]:
Pic 3[An Object as List comprising 1 List of Another Object inside it, likewise for the other 2(Accommodation & Others)]:
Pic 4[List of Object inside the sub-Object containing a byre array parameter alone]:
And my code for webservice POST method:
public static final String capUrl = "http://192.168.1.7:8084/CAPWS";
public Expenses setExpensesByBatch(Expenses expenses) {
try {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
List<HttpMessageConverter<?>> list = new ArrayList<HttpMessageConverter<?>>();
list.add(new MappingJacksonHttpMessageConverter());
restTemplate.setMessageConverters(list);
String b = restTemplate.postForObject(capUrl + "/UX/", expenses, String.class);
Log.e("String ===============b", b + " ++++");
} catch (Exception e) {
e.printStackTrace();
Log.e("expObjPost_WsCli_EX", e.toString());
}
return expenses;
}
Whatever I do it returns org.springframework.web.client.HttpClientErrorException: 415 Unsupported Media Type
My LOGCAT below:
My server side code:
#RequestMapping(value = CapRestURIConstants.UPDATEEXPENSES, method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody
String updateExpenses(#RequestBody Expenses expenses) {
String response = "true";
System.out.println("incoming--------" + "UPDATEEXPENSES");
try {
if (expenses != null) {
//System.out.println("expenses--------" + expenses);
int catType = expenses.getCategoryType();
String categoryType = String.valueOf(catType);
String categoryId = expenses.getCategoryId();
String batchId = expenses.getBatchId();
System.out.println("categoryType--------" + categoryType);
System.out.println("categoryId--------" + categoryId);
System.out.println("batchId--------" + batchId);
Batch batch = getBatchById(batchId);
if (batch != null) {
expenseDataNew(batch, expenses);
expenseImagesNew(batch, expenses);
}
}
} catch (Exception e) {
e.printStackTrace();
response = "faslse";
}
return response;
}
public void expenseDataNew(Batch batch, Expenses expenses) {
Session session = null;
Transaction transaction = null;
Gson gson = new Gson();
try {
LinkedTreeMap masterMap = (LinkedTreeMap) gson.fromJson(batch.getMasterJson(), Object.class);
LinkedTreeMap expenseObject = (LinkedTreeMap) masterMap.get("2007");
masterMap.replace(expenseObject, expenses);
String masterJson = gson.toJson(masterMap);
batch.setMasterJson(masterJson);
session = HibernateUtil.getSessionFactory().openSession();
transaction = session.beginTransaction();
session.saveOrUpdate(batch);
transaction.commit();
} catch (Exception e) {
if (transaction != null) {
transaction.rollback();
}
e.printStackTrace();
} finally {
if (session != null) {
session.close();
}
}
}
public void expenseImagesNew(Batch batch, Expenses expenses) {
Session session = null;
Transaction transaction = null;
Gson gson = new Gson();
try {
// DIVERTING TO IMAGE DB
session = ImageHibernateUtil.getSessionFactory().openSession();
transaction = session.beginTransaction();
if (expenses != null) {
int catType = expenses.getCategoryType();
String categoryType = String.valueOf(catType);
System.out.println("categoryType--------" + categoryType);
String categoryId = expenses.getCategoryId();
System.out.println("categoryId--------" + categoryId);
String travelExpenseImgId = "f257f225-41da-11e7-be05-001d92ba9634";
String accommodationExpenseImgId = "204b4baf-41db-11e7-be05-001d92ba9634";
String otherExpenseImgId = "45d31872-41db-11e7-be05-001d92ba9634";
AssessorExpense assessorExpense = expenses.getAssessorExpense();
TCExpense tCExpense = expenses.getTcExpense();
Boolean isTravel, isAccomadation, isOthers;
List<Travel> travelList;
List<Accomadation> accommodationList;
List<Others> othersList;
ArrayList proof;
Expense expense;
ExpenseImage expenseImage;
// categoryType: 1 = Assessor
// categoryType: 4 = TC
if (categoryType.equals("1")) {
if (assessorExpense != null) {
isTravel = assessorExpense.isTravel();
if (isTravel) {
travelList = (ArrayList) assessorExpense.getTravel();
System.out.println("travelList.size()==" + travelList.size());
expense = getExpense(travelExpenseImgId);
System.out.println("expense==travel==1==:" + expense);
String expenseStr = String.valueOf(expense);
System.out.println("expenseStr==travel==1==:" + expenseStr);
for (Travel travel : travelList) {
List<ExpenseImageObject> expenseImageObjects = (ArrayList) travel.getExpenseImageObjects();
System.out.println("travel==expenseImageObjects.size()== :" + expenseImageObjects.size());
for (ExpenseImageObject image : expenseImageObjects) {
System.out.println("expense===travel==for==:" + expense);
expenseImage = new ExpenseImage();
expenseImage.setBatchId(batch.getBatchId());
expenseImage.setCategoryId(expenses.getCategoryId());
expenseImage.setExpimgId(expenseStr);
expenseImage.setImage(image.getImage());
expenseImage.setStatus(1); // dummy status 1 - Travel, 2 - Accommodation, 3 - Other
session.saveOrUpdate(expenseImage);
}
}
}
}
}
}
transaction.commit();
} catch (Exception e) {
if (transaction != null) {
transaction.rollback();
}
e.printStackTrace();
} finally {
if (session != null) {
session.close();
}
}
}
I am actually trying to send an object with lists of data as well list of photos in each list to the server.
Browsed through several websites and almost all topics related to the error on Stack Overflow, Been sitting on this issue for more than a week. Hope I would find some help.
Try using "HttpHeaders" to set the content-type header explicitly to what is expected by the endpoint.
Then you use the "HttpEntity" with both your header and your body classes.
Example :
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity<String> httpEntity = new HttpEntity<>("my body", requestHeaders);
byte[] response = restTemplate.postForObject(
"URL", httpEntity, byte[].class);
Change the call to something like this
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("Accept","application/json;charset=utf-8");
RestTemplate restTemplate = new RestTemplate();
...
HttpEntity request = new HttpEntity(req, headers);
responseEntity = restTemplate.exchange(url, HttpMethod.POST, request,
String.class);
to specify content type
UPDATE
req is in fact body you send to the server. It could be e.g.
MultiValueMap<String, Object> req ...
There you in fact send request body and headers.
After a hell lot of research and experts suggestions, I finally managed to find the solution to my problem. The problem is not with the code. Its actually perfect. The problem is with the Objects I use to get & set. I am using NetBeans for server side coding. What I did was, I created my necessary Objects in Android studio, copied the parameters, getters & setters and pasted them on NetBeans, Object class. The problem was with the booleans I've been using. The booleans that are created on Android Studio didn't support on NetBeans in some cases, that prevented hitting the server. And after getting expert advice, I did the Object creation on NetBeans copied the parameters, getters & setters and pasted them on Android Studio Object class. And then it worked well. Took me more than 2 weeks to solve this issue. Hope this would be of some help.

AWS SignatureDoesNotMatch

Receiving:
SignatureDoesNotMatchThe request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.
With the following:
String associateTag = "example-20";
String awsAccessKeyId = "accessKeyId";
String awsSecretKey = "secretKey";
String endpoint = "webservices.amazon.com";
String uri = "/onca/xml";
String charset = "UTF8";
private String buildQueryString(String keywords) {
Map<String,String> params = new ArrayMap<>();
List<String> pairs = new ArrayList<>();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
params.put("Service","AWSECommerceService");
params.put("Operation","ItemSearch");
params.put("AWSAccessKeyId",awsAccessKeyId);
params.put("AssociateTag",associateTag);
params.put("SearchIndex","All");
params.put("ResponseGroup","Images,ItemAttributes");
params.put("Timestamp",sdf.format(new Date()));
params.put("Keywords", keywords);
Map<String, String> treeMap = new TreeMap<>(params);
try {
for (Map.Entry<String, String> param : treeMap.entrySet()) {
pairs.add(URLEncoder.encode(param.getKey(), charset) + "=" + URLEncoder.encode(param.getValue(), charset));
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
String queryString = "";
for (int i = 0; i < pairs.size(); i++) {
if (i != 0) {
queryString += "&";
}
queryString += pairs.get(i);
}
Log.d(TAG, "queryString: " + queryString);
return queryString;
}
private String buildSignature(String queryString) {
String hash = "";
try {
String message = "GET\n" + endpoint + "\n" + uri + "\n" + queryString;
Log.d(TAG, "message: " + message);
Mac sha_HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(awsSecretKey.getBytes(charset), "HmacSHA256");
sha_HMAC.init(secret_key);
hash = Base64.encodeToString(sha_HMAC.doFinal(message.getBytes(charset)), Base64.DEFAULT);
}
catch (Exception e){
System.out.println("Error");
}
return hash;
}
public void searchProducts(String keywords) {
String requestUrl = "";
String queryString = buildQueryString(keywords);
String signature = buildSignature(queryString);
Log.d(TAG, "signature: " + signature);
try {
requestUrl = "http://" + endpoint + uri + "?" + queryString + "&Signature=" + URLEncoder.encode(signature, charset);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
Log.d(TAG, "requestUrl: " + requestUrl);
Ion.with(context)
.load(requestUrl)
.asString()
.setCallback(new FutureCallback<String>() {
#Override
public void onCompleted(Exception e, String result) {
Log.d(TAG, "searchProducts result: " + result);
}
});
}
What could be the problem?
Make sure that your system clock is correct. It will be good idea to sync it using NTP. In the past I have seen signature errors when the time is out of sync.
What I've seen before is that this is normally down to permissions . Check access and secret key is correct and you have adequate permissions.
Changed:
Base64.DEFAULT;
To:
Base64.NO_WRAP;
It's hard to tell from the code. A few things to check:
Make sure the service you want to reach uses SigV2 signing (or query string signing). New services follow version 4 signing standard.
URLEncoder.encode doesn't meet AWS' encoding requirement RFC 3986. You need to apply some fixes to the encoded string.
Query strings should be sorted in a case insensitive way.
Your credentials are indeed correct.
It's a good idea to see how QueryStringSigner.java is implemented in the official SDK , and Signature Version 2 Signing Process.
PS: what's the reason of not using the offical SDK?
In the past when I have had this issue, it was to do with system time. Syncing time with NTP fix issue for me
Can be caused by
A space in the name (or path) of the file.
Characters that are not being properly encoded. Mostly / or +.
Generating new keys that does not contain these characters could help. More info on this issue or this one.

JSON parsing not encoding string with underscore in Android using Volley

I am trying to encode a string which contains a URL, I have a strange issue where the complete string is not being returned, I have noticed that it may be related to the underscore, I have tried a few solution where I replace the underscore, but haven't had much luck with that solution. Below is the JSON.
[{"id":"1","source":"BBC WORLD NEWS",
"time_date":"Sat, 25 Oct 2014 10:49:13",
"title":"Iran hangs woman despite campaign","description":"Iran defies an international campaign and hangs a woman who killed a man she said was trying to sexually abuse her.",
"link":"http:\/\/www.bbc.co.uk\/news\/world-middle-east-29769468#sa-ns_mchannel=rss&ns_source=PublicRSS20-sa",
"image":"http:\/\/news.bbcimg.co.uk\/media\/images\/78529000\/jpg\/_78529517_78528720.jpg"},
I am trying to retrieve the image element from the json. The following is what I receive from my parsing.
http://news.bbcimg.co.uk/media/images/78526000/jpg
I am using this code at the moment:
String imageurl = feed.getImage();
try {
imageurl = URLDecoder.decode(imageurl, "UTF-8");
System.out.println("---------------------------"+imageurl);
imageurl.replace("_", "%5f");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
getimage method:
private String image;
public String getImage() {
return image;
}
private void requestNewsData(String uri) {
RestAdapter api = new RestAdapter.Builder().setEndpoint(ENDPOINT).build();
NewsAPI restapi = api.create(NewsAPI.class);
restapi.news(new Callback<List<RssObject>>() {
public void success(final List<RssObject> newsFeed, Response response) {
Log.v("nas", "the webservice success " + response.getReason());
for (int i = 0; i < newsFeed.size(); i++) {
System.out.println(newsFeed.get(i).description);
newsList.add(newsFeed.get(i).description);
FeederModel feed = new FeederModel();
feed.setSource(newsFeed.get(i).source);
feed.setImage(newsFeed.get(i).image); // adding setimage
}
}
The retrieved string is missing the final part of the url.
Any suggestion would be gratefully appreciated. Thanks.

Categories

Resources