I need to send custom headers in my android app, I'm using the servicestack plugin for android studio http://docs.servicestack.net/java-add-servicestack-reference
In the net.servicestack.client.JsonServiceClient class exists the field
public static Connection Filter GlobalRequestFilter, Can I use it for send custom headers? thank you
Yes, you can set HTTP Headers on the AndroidServiceClient instance with:
AndroidServiceClient client = new AndroidServiceClient(baseUrl);
client.RequestFilter = new ConnectionFilter() {
#Override
public void exec(HttpURLConnection conn) {
conn.setRequestProperty("X-header", "value");
}
};
Java 8:
client.GlobalRequestFilter = conn -> conn.setRequestProperty("X-header", "value");
Or globally to all Service Client requests with:
AndroidServiceClient.GlobalRequestFilter = new ConnectionFilter() {
#Override
public void exec(HttpURLConnection conn) {
conn.setRequestProperty("X-header", "value");
}
};
Java 8:
AndroidServiceClient.GlobalRequestFilter = conn ->
conn.setRequestProperty("X-header", "value");
Related
I need a working example for a custom API for Microsoft Azure App Service.
I could not get any useful or working information/examples for that, or they just show each time different approaches which are outdated?!?!
For now I have a working table controller which gets information from database and returns it back to my Android client. Now I need to define a custom API Controller to get a string back. In the examples they are all sending an object to the service in order to get an object back. I do not want to send anything to the API, just retrieve some information back from a GET Request.
Regards
// EDIT - Added / edited client / server code to Post a String.
You can use the following code to do a GET request on the auto generated API controller Visual Studio creates (ValuesController).
private void getStringFromAzure() throws MalformedURLException {
// Create the MobileService Client object and set your backend URL
String yourURL = "https://yourApp.azurewebsites.net/";
MobileServiceClient mClient = new MobileServiceClient(yourURL, this);
// Your query pointing to yourURL/api/values
ListenableFuture<JsonElement> query = mClient.invokeApi("values", null, GetMethod, null);
// Callback method
Futures.addCallback(query, new FutureCallback<JsonElement>() {
#Override
public void onSuccess(JsonElement jsonElement) {
// You are expecting a String you can just output the result.
final String result = jsonElement.toString();
// Since you are on a async task, you need to show the result on the UI thread
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(mContext, result, Toast.LENGTH_LONG).show();
}
});
}
#Override
public void onFailure(Throwable throwable) {
Log.d(TAG, "onFailure: " + throwable.getMessage());
}
});
}
public void sendString(final String someString) throws MalformedURLException {
// Your query pointing to /api/values/{String}
ListenableFuture<JsonElement> query = mClient.invokeApi("values/" + someString, null, PostMethod, null);
// Callback method
Futures.addCallback(query, new FutureCallback<JsonElement>() {
#Override
public void onSuccess(JsonElement jsonElement) {
// You are expecting a String you can just output the result.
final String result = jsonElement.toString();
}
#Override
public void onFailure(Throwable throwable) { }
});
}
The backend API: (ValuesController)
{
// Use the MobileAppController attribute for each ApiController you want to use
// from your mobile clients
[MobileAppController]
public class ValuesController : ApiController
{
// GET api/values
public string Get()
{
return "Hello World!";
}
// POST api/values/inputString
public string Post(string inputString)
{
return inputString;
}
}
}
You can also send parameters along in the following way:
List<Pair<String, String>> parameters = new ArrayList<>();
parameters.add(new Pair<>("name", "John"));
parameters.add(new Pair<>("password", "fourwordsalluppercase"));
ListenableFuture<JsonElement> query = client.invokeApi("yourAPI", PostMethod, parameters);
Or as json in the body:
JsonObject body = new JsonObject();
body.addProperty("currentPassword", currentPassword);
body.addProperty("password", password);
body.addProperty("confirmPassword", confirmPassword);
ListenableFuture<JsonElement> query = mClient.invokeApi("yourAPI", body, PostMethod, null);
Based on my understanding, I think there are two parts in your question which include as below. And I think you can separately refer to two sections to get the answers and write your own example.
How to define a custom API on Azure Mobile App to retrieve data from database? Please refer to the section Custom APIs to know how to do with Azure Mobile App backend.
How to call a custom API from Android App? Please refer to the section How to: Call a custom API to know how to do with Android SDK.
I need to connect to a socket and send credential info in order to start receiving upcoming data over RECEIVE_CRISIS.
I'm using the library Socket.IO for Android code. It's really hard to debug since I got no Log from the connection, I don't know why and where it fails. I just never received anything from the server since I started working on the Android side. Is the NSDictionary equivalent to the JSONObject on Android? Is sendEvent equivalent to send() or emit() on Android? Do I need to send the JSON as an Object or an Array? Finally, how to I get the log error?
It's working on iOS part so I'm kinda lost..
This is the iOS code : (I modify the address for safe purpose):
NSDictionary *params=#{#"user":_username,#"orgid":_organizationId};
[_socketIO connectToHost:#"nodejs.myserver.com" onPort:3000 ];
[_socketIO sendEvent:#"joinparty" withData:params];
This is the Android code :
private void connectAndListen(int username) throws Exception {
socket = IO.socket("nodejs.myserver.com:3000");
socket.connect();
JSONObject json = new JSONObject();
json.put("user", username);
json.put("orgid", settings.getString("orgid", ""));
Log.e(TAG, json.toString());
socket.send("joinparty",json);
socket.emit("joinparty", json);
socket.on(RECEIVE_CRISIS, onCrisis);
}
UPDATED QUESTION
private void connectAndListen(int id) throws Exception {
IO.setDefaultSSLContext(SSLContext.getDefault());
// Set default hostname
HostnameVerifier hostnameVerifier = new HostnameVerifier() {
#Override
public boolean verify(String hostname, SSLSession session) {
HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
return true;
}
};
IO.setDefaultHostnameVerifier(hostnameVerifier);
IO.Options options = new IO.Options();
// set as an option
options.sslContext = SSLContext.getDefault();
options.hostnameVerifier = hostnameVerifier;
options.secure = true;
socket = IO.socket("nodejs.myserver.com:3000", options);
socket.connect();
JSONObject json = new JSONObject();
json.put("user", id);
json.put("orgid", settings.getString("orgid", ""));
Map<Object, Object> arrays = new HashMap<>();
arrays.put("user", id);
arrays.put("orgid",settings.getString("orgid", "") );
socket.emit("joinparty", arrays);
socket.on(RECEIVE_CRISIS, onCallback);
socket.on("connect_error", onCallback);
socket.on("connect", onCallback);
socket.on("Object", onCallback);
socket.on("connect_timeout", onCallback);
}
private Emitter.Listener onCallback = new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.e(TAG, args[0]+"");
}
};
Is the NSDictionary is equivalent to the JSONObject on Android?
No, it's not. NSDictionary is a class cluster, meaning that the actual implementation is hidden from you, the API user. In fact, the Foundation framework will choose the appropriate implementation at run time based on amount of data etc. The closest to it for Java is Map<Object, Object>
Is sendEvent equivalent to send() or emit() on Android?
It is emit for Android. from official documentation
DO I need to send the JSON as an Object or an Array?
Try sending a Map instead. JSON is a different thing. If your server is expecting data in JSON format, than only send it.
Finally, How to I get the log error?
You need to use combination of emitter and manager for it.
C# Code
var querystringData = new Dictionary<string, string>();
querystringData.Add("UserName", LocalSettings.UserName);
querystringData.Add("LoginId", LocalSettings.LoginId);
hubConnection = new HubConnection("http://...", querystringData);
How do I pass the Dictionary as queryString in Android
Platform.loadPlatformComponent( new AndroidPlatformComponent() );
String host = "http://....;
String qs = "";
//Instead of String I want to pass List/Dictionary
HubConnection connection = new HubConnection(host, qs, true, new ConsoleLogger());
HubProxy hub = connection.createHubProxy("calculatorHub");
Referring http://whathecode.wordpress.com/2014/03/20/getting-started-with-the-java-signalr-sdk/ as the base
The C# client basically turns the dictionary you pass to "&{key}={value}" for each KeyValuePair. So you should be able to do the same on your side and pass to the HubConnection ctor as queryString.
Here my code, works perfect
String server = URL + "signalr";
String CONNECTION_QUERYSTRING ="Bearer=" + BaseActivity.getToken(activity).getAccess_token();
HubConnection connection = new HubConnection(server, CONNECTION_QUERYSTRING, false, new Logger() {
#Override
public void log(String message, LogLevel level) {
System.out.println(message);
}
});
I'm trying to implement a pusher service in my Android app, doesn't have access to the server just copying from an iOS app previous implementation. Everything works fine in connection process but when subscribe to a private channel the authentication fails with:
"com.pusher.client.AuthorizationFailureException: java.io.FileNotFoundException: https://authorization_url"
The implementation goes like this:
HttpAuthorizer authorizer = new HttpAuthorizer(PUSHER_AUTH_URL);
PusherOptions options = new PusherOptions().setEncrypted(true).setWssPort(443).setAuthorizer(authorizer);
pusher = new Pusher(PUSHER_KEY, options);
pusher.connect(new com.pusher.client.connection.ConnectionEventListener() {
#Override
public void onConnectionStateChange(ConnectionStateChange change) {
if (change.getCurrentState() == ConnectionState.CONNECTED) {
Channel channel = pusher.subscribePrivate(PUSH_CHANNEL, new PrivateChannelEventListener() {
#Override
public void onAuthenticationFailure(String s, Exception e) {
Log.w("PUSHER", "Channel subscription authorization failed");
}
#Override
public void onSubscriptionSucceeded(String s) {
Log.w("PUSHER", "Channel subscription authorization succeeded");
}
#Override
public void onEvent(String s, String s2, String s3) {
Log.w("PUSHER", "An event with name " + s2 + " was delivered!!");
}
}, "my-event");
}
}
#Override
public void onError(String message, String code, Exception e) {
Log.w("PUSHER", "There was a problem connecting with code " + code + " and message " + message);
}
}, ConnectionState.ALL);
UPDATE
I'm sure that the problem is with the authentication, there is a function call in iOS version that set some headers to the channel subscription or something like that:
(void)pusher:(PTPusher *)pusher willAuthorizeChannel:(PTPusherChannel *)channel withRequest:(NSMutableURLRequest *)request;
{
[request addAuthorizationHeadersForUser:self.credentials.user];
}
Im trying to figure out where to add the headers in android, try to add it to the authorizer but nothing change:
authorizer.setHeaders(addMapAuthorizationHeaders());
Any idea of what is the equivalent in Android of that iOS function: willAuthorizeChannel??
Ok solved, it was what I thought, the HttpAuthorizer needed a set of headers that you can set directly when creating it like:
HttpAuthorizer authorizer = new HttpAuthorizer(PUSHER_AUTH_URL);
authorizer.setHeaders(MY_AUTH_HEADERS); //a HashMap with the headers
PusherOptions options = new PusherOptions().setEncrypted(true).setWssPort(443).setAuthorizer(authorizer);
pusher = new Pusher(PUSHER_KEY, options);
And with that works fine, in case somebody have a similar problem.
EDIT:
this is how to set the authorization headers. It's a Map set to "Key" "Value" pair for example:
public static HashMap<String, String> getMapAuthorizationHeaders() {
try {
HashMap<String, String> authHeader = new HashMap<>();
authHeader.put("HeaderKey1", "HeaderValue1");
authHeader.put("HeaderKey2", "HeaderValue2");
return authHeader;
} catch (Exception e) {
return null;
}
}
So the pusher config will be like:
authorizer.setHeaders(getMapAuthorizationHeaders());
I've been struggling with this as well... the solution is simple.
First check this out: https://github.com/pusher/pusher-websocket-java/blob/master/src/main/java/com/pusher/client/util/HttpAuthorizer.java
Then implement the abstract interface Authorizer and override the authorize method with your own code and that's it, you get the same thing as on the iOS.
Some snippet to get you started (with a custom constructor):
CustomSocketHttpAuthorizer authorizer = new CustomSocketHttpAuthorizer(ServerComm.API_MAIN_LINK + ServerComm.API_LINK_PUSHER_AUTH, pusherServerAuthTimeStamp, MessageActivity.this);
PusherOptions options = new PusherOptions().setAuthorizer(authorizer).setEncrypted(true);;
clientPusher = new Pusher(ServerComm.PUSHER_CLIENT_KEY, options);
clientPusher.connect(new ConnectionEventListener() .....
I am trying to get responses from a JSON-RPC Service on Android, I'm currently developing on 3.0 Honeycomb.
This is the library I am using:
http://code.google.com/p/android-json-rpc/
and I am using this JSON-RPC service page for testing:
http://www.raboof.com/projects/jayrock/demo.ashx
The connection seems to work, but I keep getting this Exception
org.alexd.jsonrpc.JSONRPCException: Invalid JSON response
I've tried different methods and survey pages, but I always get the same Exception. Where am I going wrong?
The relevant code is below. AsyncTask is used because since 3.0 Android doesn't allow network connections in the main stream. Thanks in advance.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
JSONHandler task = new JSONHandler();
task.execute(new String[] {"http://www.raboof.com/projects/jayrock/demo.ashx"});
}
private class JSONHandler extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
for (String url : urls) {
JSONRPCClient client = JSONRPCClient.create(url);
client.setConnectionTimeout(2000);
client.setSoTimeout(2000);
try {
client.call("counter");
} catch (JSONRPCException e) {
e.printStackTrace(); //Invalid JSON Response caught here
}
}
return null;
}
}
I have tested your system using the last version of the library. It work great. You need to us callInt("counter") and it will be ok.
There is the code I used:
public JSONRPCClient client = JSONRPCClient.create("http://www.raboof.com/projects/jayrock/demo.ashx", JSONRPCClient.Versions.VERSION_2);
try{
int resInt = client.callInt("counter");
} catch (JSONException e) {
Log.i("JSON-RPC Client", e.toString());
}
I hope this can help.
PS: with this new version, you use parameters send as an array, or using a JSONObject to send named parameters. This is only possible if using the version 2.0 of the JSON-RPC protocol.
This is the only JSON-RPC client I've been able to get to work with Zend_Json_Server on Android (and I've tried a few).
Make sure to set the version to 2.0 also, as this client doesn't work unless your server is explicitly using the 2.0 spec:
$server = new Zend_Json_Server();
$server->setClass('My_Class');
$server->getRequest()->setVersion("2.0");
if ('GET' == $_SERVER['REQUEST_METHOD']) {
// Indicate the URL endpoint, and the JSON-RPC version used:
$server->setTarget('/ajax.php')
->setEnvelope(Zend_Json_Server_Smd::ENV_JSONRPC_2);
// Grab the SMD
$smd = $server->getServiceMap();
// Return the SMD to the client
header('Content-Type: application/json');
echo $smd;
return;
}
$server->handle();