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();
Related
I'm new to android and not much aware about it. I though have been through tutorial but still didn't get any solution. How to connect Android Studio with postgressql? Step by step!
I wrote this code in my MainActitvity.java. Is this correct? Or should I write it else where?
static final String JDBC_DRIVER = "org.postgresql.Driver";
static final String DB_URL = "jdbc:postgresql://localhost:5432/user1";
// Database credentials
static final String USER = "root";
static final String PASS = "root";
public static void main(String[] args)
{
Connection conn = null;
Statement st = null;
try{
//STEP 2: Register JDBC driver
Class.forName("org.postgresql.Driver");
//STEP 3: Open a connection
System.out.println("Connecting to database...");
conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/","root","root");
//STEP 4: Execute a query
System.out.println("Creating statement...");
st = conn.createStatement();
String sql;
sql = "SELECT first, last FROM Employees";
ResultSet rs = st.executeQuery(sql);
//STEP 5: Extract data from result set
while(rs.next()){
//Retrieve by column name
String first = rs.getString("first");
String last = rs.getString("last");
//Display values
System.out.print(", First: " + first);
System.out.println(", Last: " + last);
}
//STEP 6: Clean-up environment
rs.close();
st.close();
conn.close();
}catch(SQLException se){
//Handle errors for JDBC
se.printStackTrace();
}catch(Exception e){
//Handle errors for Class.forName
e.printStackTrace();
}
finally
{
//finally block used to close resources
try{
if(st!=null)
st.close();
}catch(SQLException se2){
}// nothing we can do
try{
if(conn!=null)
conn.close();
}
catch(SQLException se){
se.printStackTrace();
}//end finally try
}
}
use 10.0.2.2 instead of localhost, it works for me.
You cannot directly use java.sql.DriverManger, Connection, etc in Android. Android support SQLite DB, if you want to use DB in android you have to go with SQLite database. For Postgres you have to develop server side application and api services which you can the call from Android
Okay, this may be obsolete but still helpful for users (it was helpful for me)
I copied your example and worked with it because I also need to get postgres running on android. And it works!
conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/","root","root");
This will result in an error because you need to enter the database name without a slash at the and, like:
conn = DriverManager.getConnection("jdbc:postgresql://domain.com:5432/databaseName", "username", "password");
Network connections (like connection to database) must be done in an AsyncTask using doInBackground(). I did it inside an activity
public class dbactivity extends AppCompatActivity { //sry code formatting just broke
String message = null;
String conmsg = null;
private class pgsqlcon extends AsyncTask<Void, Void, Void>
{
public pgsqlcon()
{
super();
}
#Override
protected Void doInBackground(Void... voids) {
Connection conn = null;
Statement st = null;
try
{
//STEP 2: Register JDBC driver
Class.forName("org.postgresql.Driver");
//STEP 3: Open a connection
System.out.println("Connecting to database...");
message = "Connecting to database...";
conn = DriverManager.getConnection("jdbc:postgresql://serverdomain.com:5432/databasename",
"dbusername", "password");
//and so on
If you need to make UI changes like setText, you must use runOnUiThread like so ():
//using quote because code formatting doesn't work anymore for me xD
private void setAsyncText(final TextView text,final String value){
runOnUiThread(new Runnable() {
#Override
public void run() {
if (value == null)
text.setText("null");
else
text.setText(value);
}
});
}
Oh yeah and last but not least, since I wrote this inside an Activiy, I have to trigger the trouble by calling my asynctask in OnCreate() of my Activity.
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dbactivity);
pgsqlcon pgcon = new pgsqlcon();
pgcon.execute();
}
}
I am not that experienced by myself so you can use this only for getting a connection at all to your postgresdb using JDBC only. Although I managed to get successful query results that way.
And again, sorry for the wrong code formatting. I did what they wanted (4 space rule etc.) and it didn't work. I hope you can read it anyway, good luck.
And if nothing of this does work, maybeeee you want to take a look at these little hints: https://jdbc.postgresql.org/documentation/head/prepare.html
(I assume you did that anyway since you have done a lot of almost correct code)
My app uses PostgreSQL as backend. Use the retrofit library for connecting to the backend. In my app backend is written in python which will make queries in the database. This will make the front-end codes more smooth and secure. And the more controls can be shifted to the back-end.
You can not connect the database with android studio directly,
you have to make connection with your application and database through api ,
and you can write your api in java, php etc.
?php
$db_connection = pg_connect("host=localhost dbname=record user=postgres password= ''");
//pg query
?>
This is your connect query api.
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 am facing an issue calling .net .asmx web service with parameter using android volley library.
Without parameter its working fine.
This my web service
[WebMethod]
private string MN_InsEOMTestScoreDetailsIndividual(string data)
{
ArrayList arrReturnDetails = new ArrayList();
bool bReturn = false;
string errMsg = globalErrMsg;
try
{
Dictionary<string, object> dicData = JsonConvert.DeserializeObject<Dictionary<string, object>>(data);
bReturn = InsEOMTestScoreDetailsIndividual(dicData["eomTSIndvlDetId"].ToString().Trim(), dicData["eomTRDetId"].ToString().Trim(), dicData["eomTSSummDetId"].ToString().Trim(),
dicData["studCode"].ToString().Trim(), dicData["ctrCode"].ToString().Trim(), dicData["batCode"].ToString().Trim(), dicData["phCode"].ToString().Trim(), dicData["pcCode"].ToString().Trim(),
dicData["tmCode"].ToString().Trim(), dicData["testActualDur"].ToString().Trim(),
dicData["testAttemptDur"].ToString().Trim(), dicData["testTtlMks"].ToString().Trim(), dicData["mksObt"].ToString().Trim(), dicData["ttlQues"].ToString().Trim(),
dicData["rAnsCnt"].ToString().Trim(), dicData["wAnsCnt"].ToString().Trim(), dicData["attemptTestDate"].ToString().Trim(),
dicData["isSolViewed"].ToString().Trim(), dicData["quesXML"].ToString().Trim(), out errMsg);
}
catch (Exception ex)
{
ErrorHandler.LogError("WebService:APP_UserActivityDetails", "M_InsEOMTestScoreDetailsIndividual", ex);
}
arrReturnDetails.Add(new
{
b = bReturn,
err = errMsg
});
return JsonConvert.SerializeObject(arrReturnDetails);
}
Your web service is probably a GET web service which you are trying to invoke as POST. That won't work. There are two ways to correct this:
Make sure your web service is of POST type and then add your parameters as a HashMap in the Volley request.
If you want to keep the web service as a GET, then append the parameters manually to the URL string (i.e. don't pass them as key-value pairs in a HashMap).
i would like to use apigee android sdk in android app. By using android sdk, I would like to connect apigee end point proxy but api proxy has got Oauth 2.0 verification. How to access our proxy?
//Create client entity
String ORGNAME = "your-org";
String APPNAME = "your-app";
ApigeeClient apigeeClient = new ApigeeClient(ORGNAME,APPNAME);
DataClient dataClient = apigeeClient.getDataClient();
String type = "item"; //entity type to be retrieved
Map queryString = null; //we don't need any additional query parameters, in this case
//call getCollectionAsync to initiate the asynchronous API call
dataClient.getCollectionAsync(type, queryString, new ApiResponseCallback() {
//If getEntitiesAsync fails, catch the error
#Override
public void onException(Exception e) {
// Error
}
//If getCollectionAsync is successful, handle the response object
#Override
public void onResponse(ApiResponse response) {
try {
if (response != null) {
// Success
}
} catch (Exception e) { //The API request returned an error
// Fail
}
}
});
There is currently no support for OAuth in the Android SDK.
I am trying to send an object to a server i wrote. I have only just learnt about AsyncTask and am trying to use it in order to keep networking tasks off the main thread. It is currently making the connection but is not receiving the object. I know the server is fine because I have tested it using code written to send the object from my laptop. Also I am not receiving any error messages.
Code:
private class sendToServer extends AsyncTask<UserObject, Integer, Double> {
#Override
protected Double doInBackground(UserObject...userObjects) {
ObjectOutputStream oos = null;
String Header = "GPSUpdate";
String Userid = "07000000001";
String Latitude = "6.00";
String Longitude = "6.00";
try{
Socket socket = new Socket("igor.gold.ac.uk", 3000);
oos = new ObjectOutputStream(socket.getOutputStream());
UserObject [] userObject = new UserObject[1];
userObject[0] = new UserObject();
userObject[0].setHeader(Header);
userObject[0].setUserid(Userid);
userObject[0].setLatitude(Latitude);
userObject[0].setLongitude(Longitude);
oos.writeObject(userObject[0]);
oos.flush();
oos.close();
}
catch(Exception e){
}
return null;
}
#Override
protected void onProgressUpdate(Integer... progress) {
}
#Override
protected void onPostExecute(Double result) {
}
}
Also the code to send the object works when ran from my laptop. Do I have to set permissions or anything different if I'm using AsyncTask to handle network operations.
Thanks for any help given.
You have an empty block catching all exceptions! At least log what's going on in there...
Does your app have the INTERNET permission declared in its manifest?
Does UserObject implement Serializable?
I found the problem it was my own simple mistake. All the code was fine but the Object being sent was in a different package on the server than the one being sent. Updated them so they are both in the same package in their respective location.