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.
Related
I have a wearable app. The app after it finishes has data like time/date, UUID, Geo location, parameters selected displayed in front of me like a Data Report or Log in several TextViews underneath each other. Like a list. I want this data to be transferred from my wearable device to my android phone.
Now I have to ask does the WearOS app the pairs the phone with the watch enables such a thing? Like can the data be sent through it? OR what exactly can I do? I read about Sync data items with the Data Layer API in the documentation, but I'm not sure if the code snippets provided would help achieve what I want.
public class MainActivity extends Activity {
private static final String COUNT_KEY = "com.example.key.count";
private DataClient dataClient;
private int count = 0;
...
// Create a data map and put data in it
private void increaseCounter() {
PutDataMapRequest putDataMapReq = PutDataMapRequest.create("/count");
putDataMapReq.getDataMap().putInt(COUNT_KEY, count++);
PutDataRequest putDataReq = putDataMapReq.asPutDataRequest();
Task<DataItem> putDataTask = dataClient.putDataItem(putDataReq);
}
...
}
The data I display in the textviews are called through methods that I call things like: getLocation, getUUID, getDateTime, getSelections, etc... when I click a button I call them in the setOnClickListener. I want this data in the TextViews to be placed in a file or something like that and send them over to the mobile phone from the watch when they're generated.
private void getDateTime()
{
SimpleDateFormat sdf_date = new SimpleDateFormat("dd/MM/yyyy");
SimpleDateFormat sdf_time = new SimpleDateFormat("HH:mm:ss z");
String currentDate= sdf_date.format(new Date());
String currentTime= sdf_time.format(new Date());
textView_date_time.setText("Date: "+currentDate+"\n"+"Time: "+currentTime);
}
#SuppressLint("SetTextI18n")
private void getUUID()
{
// Retrieving the value using its keys the file name
// must be same in both saving and retrieving the data
#SuppressLint("WrongConstant") SharedPreferences sh = getSharedPreferences("UUID_File", MODE_APPEND);
// The value will be default as empty string because for
// the very first time when the app is opened, there is nothing to show
String theUUID = sh.getString(PREF_UNIQUE_ID, uniqueID);
// We can then use the data
textView_UUID.setText("UUID: "+theUUID);
}
#SuppressLint("SetTextI18n")
private void getSelections()
{
textView_data_selected.setText("Tool No.: "+c.getToolNo()+
"\nTool Size: " +c.getToolSizeStr()+
"\nFrom Mode: " +c.getCurrentModeStr()+
"\nGoto Mode: " +c.getModeStr()+
"\nMethod: " +c.getMethodStr()+
"\nBit Duration: " +c.getBitDuration()+
"\nUpper bound" +c.getUpStageValue()+
"\nLower bound: "+c.getDownStageValue());
}
The above are examples of the methods I use to get the data. then I call them here:
gps_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (Build.VERSION.SDK_INT >= 26) {
getLocation();
getDateTime();
getUUID();
getSelections();
}
else
{
//ActivityCompat.requestPermissions(get_location.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
Toast.makeText(get_location.this,"Build SDK too low",Toast.LENGTH_SHORT);
}
}
});
Now how do I take all this and send it over from my device to the the phone?
Note: The data report I want to send as a file, I want it done subtly like something done in the background. I don't know what else to do or where to look.
You have two options if you want to use the Data Layer, one is to use the MessageClient API to bundle your data up in a message and send it directly to the handheld. The easiest here would be to create an arbitrary JSONObject and serialize your data as a JSON string you can stuff into a message. For example:
try {
final JSONObject object = new JSONObject();
object.put("heart_rate", (int) event.values[0]);
object.put("timestamp", Instant.now().toString());
new MessageSender("/MessageChannel", object.toString(), getApplicationContext()).start();
} catch (JSONException e) {
Log.e(TAG, "Failed to create JSON object");
}
In my case, I do this in my onSensorChanged implementation, but you can insert this wherever you are updating your text.
MessageSender is just a threaded wrapper around the MessageClient:
import java.util.List;
class MessageSender extends Thread {
private static final String TAG = "MessageSender";
String path;
String message;
Context context;
MessageSender(String path, String message, Context context) {
this.path = path;
this.message = message;
this.context = context;
}
public void run() {
try {
Task<List<Node>> nodeListTask = Wearable.getNodeClient(context.getApplicationContext()).getConnectedNodes();
List<Node> nodes = Tasks.await(nodeListTask);
byte[] payload = message.getBytes();
for (Node node : nodes) {
String nodeId = node.getId();
Task<Integer> sendMessageTask = Wearable.getMessageClient(context).sendMessage(nodeId, this.path, payload);
try {
Tasks.await(sendMessageTask);
} catch (Exception exception) {
// TODO: Implement exception handling
Log.e(TAG, "Exception thrown");
}
}
} catch (Exception exception) {
Log.e(TAG, exception.getMessage());
}
}
}
The other option is to create a nested hierarchy of data items in the Data Layer and implement DataClient.OnDataChangedListener on both sides, such that changes that are written in on one side are automatically synchronized with the other. You can find a good walkthrough on how to do that here.
For your specific case, just packing it in a JSON object would probably be the simplest. The writing out to your preferred file format you can then implement on the handheld side without needing to involve the wear side.
I want to observer changes from server in my android app.
So I'm using this interface for open stream with server.
public interface Service {
#GET("/n/{id}/streaming")
void streamThreads(#Path("name_space_id") String Id, #QueryMap Map<String, String> options,#Query("exclude_types") String type, Callback<Object> callback);
}
and this is my method where I can get response in my activity
server.streamThreads(accountInfo.getId(), map, "thread", new Callback<Object>() {
#Override
public void success(Object o, Response response) {
String json = (String) o;
Log.i(TAG,json);
}
#Override
public void failure(RetrofitError error) {
Response r = error.getResponse();
if (r != null)
Log.e(TAG, "error: " + r.getReason());
}
});
So I tested method in web browser and life stream works.
But response comes in my mobile app every 30 minutes. I'm using one activity and call method onCreate().
Thanks
Retrofit provides an #Streaming annotation.
The unread byteStream can then be obtained from the raw OkHttp ResponseBody.
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 want to show Facebook Page's Notes items with those comments and likes using Graph API.
To do that, I'm using the asyncFacebookRunner in Facebook SDK.
Steps are like this:
call asyncFacebookRunner.request to get Note Item with PageId
mAsyncRunner.request(sAPIString, new NotesRequestListener(), null);
Response has come. ( I can't highlight function call. Sorry for inconvenient to find it.)
public class NotesRequestListener implements com.facebook.android.AsyncFacebookRunner.RequestListener
{
/**
* Called when the request to get notes items has been completed.
* Retrieve and parse and display the JSON stream.
*/
#Override
public void onComplete(String response, Object state) {
// TODO Auto-generated method stub
Log.i("My_TAG", "onComplete with response, state");
try
{
// process the response here: executed in background thread
final JSONObject json = new JSONObject(response);
JSONArray arrNotesItems = json.getJSONArray("data");
int l = (arrNotesItems != null ? arrNotesItems.length() : 0);
// !!!!
// This has another request call
// !!!!
final ArrayList<WordsItem> newItems = WordsItem.getWordsItems(arrNotesItems,getActivity());
WordsActivity.this.runOnUiThread(new Runnable() {
public void run() {
wordsItems.clear();
wordsItems.addAll(newItems);
aa.notifyDataSetChanged();
}
}); // runOnUiThread
} // try
catch (JSONException e)
{
Log.i("My_TAG", "JSON Error in response");
} // catch
} // onComplete
... other override methods ...
} // Request Listener
< Another Class >
public static ArrayList<WordsItem> getWordsItems(JSONArray arrJSON, Activity activity) {
ArrayList<WordsItem> wordsItems = new ArrayList<WordsItem>();
int l = (arrJSON != null ? arrJSON.length() : 0);
try {
WordsItem newItem;
for (int i=0; i<l; i++) {
JSONObject jsonObj = arrJSON.getJSONObject(i);
String sTitle = jsonObj.getString("subject");
String sNoteID = jsonObj.getString("id");
... get another fields here ...
newItem = new WordItem(...);
// !!!!
// This has request call for comments
// !!!!
ArrayList<CommentItem> arrComment = getUserComments(sNoteID);
wordsItems.add(newItem);
}
} catch (Exception e) {
e.printStackTrace();
}
return wordsItems;
} // getWordsItems
call another asyncFacebookRunner.request to get comments of item(with NoteID)
in getUserComments
mAsyncRunner.request(sAPIString, new CommentRequestListener(), null);
Before getting comments(OnComplete in CommentRequestListener has not called), getWordsItems returns item array.
So I can't see the comments.
How can I wait to update UI till getting comments?
(It's so ironic to synchronize asynchronized calls.)
Thanks in advance.
Use facebook object which has non-asynchronous request method.
You need not implement listener method.
So, I suggest below means.
use mAsyncRunner.request for first request call.
use mFacebookRunner.request for second request call.
I hope it may help you:-)
Using FQL - Facebook Query Language you can easily get all this information about any particular note info
, Also to get likes on that and comments over it as like examples given in the links.
I am trying to develop a Facebook application for Android. I am unable to integrate the "Add Comment" feature to photos in Facebook Albums. Using the Graph API, I can show the previously made comments on a photo. However, I just can't add new comments to a photo.
Can somebody provide me some helpful advice?
here is simple example on doing that..
// post comment to single photo
Bundle parameters = new Bundle();
String target = "";
target = "<PHOTO_ID>/comments";
parameters.putString("message", "post Comment testing");
mAsyncRunner.request(target, parameters, "POST", new FacebookRequestListener(target+" (post comment)"));
and here is a simple example for the listener (you can get this from examples of facebook-android-sdk too)
public class FacebookRequestListener extends BaseRequestListener {
String caller = "default";
public FacebookRequestListener() {
}
public FacebookRequestListener(String caller) {
this.caller = caller;
}
public void onComplete(final String response) {
try {
Log.d(TAG, "FacebookRequestListener|"+caller+":" + response);
} catch (Exception e) {
Log.w(TAG, "Error:"+e.getMessage());
}
}
}