So I am using the AccountManager from Android to store OAuth2 credentials. These credentials are then used in the getAuthToken method, as any other account manager works. Here is my getAuthToken method:
#Override
public Bundle getAuthToken(AccountAuthenticatorResponse response, final Account account, String authTokenType, Bundle options) throws NetworkErrorException {
Log.d(TAG, "onGetAuthToken");
final AccountManager am = AccountManager.get(context);
String storeToken = am.peekAuthToken(account, authTokenType);
final String password = am.getPassword(account);
if (TextUtils.isEmpty(storeToken) && password != null) {
storeToken = new OAuth2Client(account.name, password, "test", "test", Constants.getServerUrlBase() + "token.php").getAccessToken().getAccessToken();
} else {
if (password != null) {
final Bundle result = new Bundle();
String authToken = null;
// Network stuff
JSONObject JSONResult;
DefaultHttpClient httpClient = new DefaultHttpClient(new BasicHttpParams());
HttpPost httppost = new HttpPost(Constants.SERVER_URL_BASE + "verify.php");
List<NameValuePair> pairs = new ArrayList<>();
pairs.add(new BasicNameValuePair("access_token", storeToken));
try {
httppost.setEntity(new UrlEncodedFormEntity(pairs));
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "onFailed Posting\n" + e);
}
InputStream inputStream = null;
try {
HttpResponse httpResponse = httpClient.execute(httppost);
HttpEntity entity = httpResponse.getEntity();
inputStream = entity.getContent();
// json is UTF-8 by default
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"), 8);
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line).append("\n");
}
Log.d(TAG + "." + this.getClass().getEnclosingMethod(), "onReceivedData " + sb.toString());
JSONResult = new JSONObject(sb.toString());
if (JSONResult.getBoolean("success"))
authToken = storeToken;
} catch (JSONException | IOException e) {
Log.e(TAG, "onCrashed\n", e);
} finally {
if (inputStream != null) try {
inputStream.close();
} catch (IOException e) {
Log.e(TAG, "Failed on inputStream!\n", e);
}
}
if (authToken == null) {
authToken = new OAuth2Client(account.name, password, "corentec_logistics_application", "corentec123", Constants.getServerUrlBase() + "token.php").getAccessToken().getAccessToken();
am.invalidateAuthToken(Constants.ACCOUNT_TYPE, storeToken);
am.setUserData(account, AccountManager.KEY_AUTHTOKEN, authToken);
}
result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
result.putString(AccountManager.KEY_AUTHTOKEN, authToken);
Log.d(TAG, "onPostExecute with String: " + authToken);
return result;
}
}
final Intent intent = new Intent(context, AuthenticatorActivity.class);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
intent.putExtra(AuthenticatorActivity.ARG_ACCOUNT_TYPE, account.type);
intent.putExtra(AuthenticatorActivity.ARG_AUTH_TYPE, authTokenType);
final Bundle bundle = new Bundle();
bundle.putParcelable(AccountManager.KEY_INTENT, intent);
return bundle;
}
Basically, this gains the user credentials, checks with the server if the token is still valid or expired. If the token is expired, it gains a new one from the server and returns that. If the token was still good, then it just returns the given token. All of this is obviously in a bundle, as required by the overridden class. This method I am having called from my application class for a more centralized approach. Here is the important part of the application class:
public String getAuthToken() {
String token = null;
final String[] authToken = {null};
GetToken getToken = new GetToken();
getToken.execute();
try {
authToken[0] = getToken.get();
return authToken[0];
} catch (InterruptedException | ExecutionException e) {
Log.e(TAG, "onCrashed\n", e);
}
return null;
}
And ...
private class GetToken extends AsyncTask<Void, Void, String> {
String token = null;
#Override
protected String doInBackground(Void... params) {
Log.d(TAG, "onDoInBackgroundExecute");
try {
token = accountManager.getAuthToken(getCurrentAccount(), Constants.TOKEN_TYPE, null, null, null, null).getResult().getString(AccountManager.KEY_AUTHTOKEN);
Log.d(TAG, "Finished getting token: " + token);
} catch (OperationCanceledException | IOException | AuthenticatorException e) {
Log.e(TAG, "onCrashed getting token\n", e);
}
return token;
}
}
I then have an activity calling this by means of:
application.setCurrentAccount(new Account(intent.getStringExtra(AccountManager.KEY_ACCOUNT_NAME), Constants.ACCOUNT_TYPE));
String token = application.getAuthToken();
With application being an instance of the Application class.
However, this hangs the activity. Logcat and Thread Snapshots say it is due to this line:
token = accountManager.getAuthToken(getCurrentAccount(), Constants.TOKEN_TYPE, null, null, null, null).getResult().getString(AccountManager.KEY_AUTHTOKEN);
inside of the ASyncTask GetToken. I cannot figure out why this is hanging and going ANR. Can anyone help?
Related
Everything seems to be fine except for the JSON exception error.
Here it is specifically: org.json.JSONException:
Value username of type `java.lang.String` cannot be converted to `JSONObject`.
There are a number of other flags that I can check in logcat and everything seems pretty good except that. I think the problem is that I need to convert the String encodedStr into a JSON object and return it to ASYNC TASK.
private class AsyncDataClass extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
//Use HashMap, it works similar to NameValuePair
Map<String, String> dataToSend = new HashMap<>();
dataToSend.put("username", params[1]);
dataToSend.put("password", params[2]);
//Server Communication part - it's relatively long but uses standard methods
//Encoded String - we will have to encode string by our custom method (Very easy)
String encodedStr = getEncodedData(dataToSend);
//Will be used if we want to read some data from server
BufferedReader reader = null;
//Connection Handling
try {
//Converting address String to URL
URL url = new URL(serverUrl);
//Opening the connection (Not setting or using CONNECTION_TIMEOUT)
HttpURLConnection con = (HttpURLConnection) url.openConnection();
//Post Method
con.setRequestMethod("POST");
//To enable inputting values using POST method
//(Basically, after this we can write the dataToSend to the body of POST method)
con.setDoOutput(true);
OutputStreamWriter writer = new OutputStreamWriter(con.getOutputStream());
//Writing dataToSend to outputstreamwriter
writer.write(encodedStr);
//Sending the data to the server - This much is enough to send data to server
//But to read the response of the server, you will have to implement the procedure below
writer.flush();
//Data Read Procedure - Basically reading the data comming line by line
StringBuilder sb = new StringBuilder();
reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
String line;
while ((line = reader.readLine()) != null) { //Read till there is something available
sb.append(line + "\n"); //Reading and saving line by line - not all at once
}
line = sb.toString();//Saving complete data received in string, you can do it differently
//Just check to the values received in Logcat
Log.i("custom_check", "The values received in the store part are as follows:");
Log.i("custom_check", line);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close(); //Closing the
} catch (IOException e) {
e.printStackTrace();
}
}
}
//Same return null, but if you want to return the read string (stored in line)
//then change the parameters of AsyncTask and return that type, by converting
//the string - to say JSON or user in your case
**strong text**return encodedStr;**strong text**
**strong text**HERE IS THE PROBLEM I BELIEVE.
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
System.out.println("Resulted Value: " + result);
if (result.equals("") || result == null) {
Toast.makeText(MainActivity.this, "Server connection failed", Toast.LENGTH_LONG).show();
return;
}
int jsonResult = returnParsedJsonObject(result);
if (jsonResult == 0) {
Toast.makeText(MainActivity.this, "Invalid username or password", Toast.LENGTH_LONG).show();
return;
}
if (jsonResult == 1) {
Intent intent = new Intent(MainActivity.this, LoginActivity.class);
intent.putExtra("USERNAME", enteredUsername);
intent.putExtra("MESSAGE", "You have been successfully login");
startActivity(intent);
}
}
private int returnParsedJsonObject(String result) {
JSONObject resultObject = null;
int returnedResult = 0;
try {
resultObject = new JSONObject(result);
returnedResult = resultObject.getInt("success");
} catch (JSONException e) {
e.printStackTrace();
}
return returnedResult;
}
}
private StringBuilder inputStreamToString(InputStream is) {
String rLine = "";
StringBuilder answer = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
try {
while ((rLine = br.readLine()) != null) {
answer.append(rLine);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return answer;
}
//************getEncodedData*****************//
private String getEncodedData(Map<String,String> data) {
StringBuilder sb = new StringBuilder();
for(String key : data.keySet()) {
String value = null;
try {
value = URLEncoder.encode(data.get(key), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
if(sb.length()>0)
sb.append("&");
sb.append(key + "=" + value);
}
return sb.toString();
}`enter code here`
Here... I have a Web API with a MessageController that will respond to my request from Android and send JSON (Hello World - Just to test it out).
public class MessageController : ApiController
{
public async Task<IHttpActionResult> SendAsync()
{
return Ok(new { text = "hello world" });
}
}
From my Android App I want to request JSON from my API. I have requested from other Web APIs like currency etc. And it worked, but same method don't work on my API.
Here it is:
public void requestMessagesFromApi(View v)
throws ClientProtocolException, IOException {
final String response = getJSON(finalUrl);
TextView msgTV = (TextView) findViewById(R.id.msgTxt);
msgTV.setText(response);
}
public String getJSON(String url) {
HttpURLConnection c = null;
try {
URL u = new URL(url);
c = (HttpURLConnection) u.openConnection();
c.setRequestMethod("GET");
c.setRequestProperty("Content-length", "0");
c.setUseCaches(false);
c.setAllowUserInteraction(false);
int status = c.getResponseCode();
switch (status) {
case 200:
case 201:
BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line+"\n");
}
br.close();
return sb.toString();
}
} catch (MalformedURLException ex) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex);
} finally {
if (c != null) {
try {
c.disconnect();
} catch (Exception ex) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex);
}
}
}
return null;
}
I get ResonseCode -1. Don't know why. In Final URL I am targeting my Web API on Azure:
finalUrl ="http://<hereIsMineWebApiURL>/api/message"
I'm sure that I'm wrong in API.
I am downloading a very huge JSON and it takes a lot of time.
I want to show the percentage of data I have downloaded.
I searched and found how to display progress if downloading a file but not JSON.
Here is how I am downloading JSON
private String getStringFromURL(String url) {
String string = null;
try {
HttpClient client = new DefaultHttpClient();
url = url.replace(" ", "%20");
url = url.replace("|", "%7C");
HttpGet get = new HttpGet(url);
HttpResponse response = client.execute(get);
if (response.getStatusLine().getStatusCode() == 200) {
String result = EntityUtils.toString(response.getEntity(),
HTTP.UTF_8);
if (result.toLowerCase().contains("invalid"))
return null;
result = result.replace("\r", "");
result = result.replace("\n", "").replace("\t", "\\t")
.replace("\b", "\\b").replace("\f", "\\f")
.replace("&", "\\&").replace("\'", "\\'")
.replace(";", "\\;").replace("?", "\\?")
.replace("*", "\\*");
string = result;
}
} catch (Exception e) {
e.printStackTrace();
}
return string;
}
You better to use AsyncTask to download data. There is a sample code below. I did not test it but it should work.
private class FetchJsonTask extends AsyncTask<Void, Void, String> {
private ProgressDialog progressDialog;
private Context context;
public FetchJsonTask(Context context) {
this.context = context;
}
#Override
protected void onPreExecute() {
// set up progress dialog
progressDialog = new ProgressDialog(context);
progressDialog.setIndeterminate(true);
progressDialog.setMessage("Please wait...");
// show it
progressDialog.show();
}
#Override
protected String doInBackground(Void... params) {
// These two need to be declared outside the try/catch
// so that they can be closed in the finally block.
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
// Will contain the raw JSON response as a string.
String jsonStr = null;
try {
// Construct the URL somehow
URL url = createURL();
// Create the request to MuslimSalat.com, and open the connection
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
// Nothing to do.
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
// Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
// But it does make debugging a *lot* easier if you print out the completed
// buffer for debugging.
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
jsonStr = buffer.toString();
} catch (IOException e) {
Log.e(LOG_TAG, "Error ", e);
// If the code didn't successfully get the data, there's no point in attemping
// to parse it.
return null;
} finally{
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e(LOG_TAG, "Error closing stream", e);
}
}
}
return jsonStr;
}
#Override
protected void onPostExecute(String jsonString) {
// jsonString is your result use it somehow.
Log.d(LOG_TAG, "Json result: " + jsonString);
// dismiss the progress because downloading process is finished.
progressDialog.dismiss();
}
}
You can call it from your activity, fragment etc.
FetchJsonTask fetchJsonTask = new FetchJsonTask(context);
fetchJsonTask.execute();
i would like to write data in an external mysql database with my android app.
this class works for that:
public class SendingData extends AppCompatActivity {
Intent intent = null;
private class LoadingDataURL extends AsyncTask<String, String, JSONArray> {
#Override
protected JSONArray doInBackground(String... params) {
URL url;
HttpURLConnection urlConnection = null;
JSONArray response = new JSONArray();
try {
url = new URL(params[0]);
urlConnection = (HttpURLConnection) url.openConnection();
int responseCode = urlConnection.getResponseCode();
String responseString = readStream(urlConnection.getInputStream());
intent = new Intent(SendingData.this, Overview.class);
startActivity(intent);
response = new JSONArray(responseString);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (urlConnection != null)
urlConnection.disconnect();
}
return response;
}
private String readStream(InputStream in) {
BufferedReader reader = null;
StringBuffer response = new StringBuffer();
try {
reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
String line = "";
while ((line = reader.readLine()) != null) {
response.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return response.toString();
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.loading_data);
String firstname = "Max";
String secondname= "Mustermann";
LoadingDataURL client = new LoadingDataURL();
client.execute("https://domain.com/index.php?"+
"fristname="+fristname+
"&secondname="+secondname);
}
}
My Problem is, that if in my strings (fristname, secondname) is an & or ? or any special characters, the entry will not be save correctly.
any ideas? :)
Use the URLEncoder class.
Try this please
String fn = URLEncoder.encode(fristname, "utf-8");
String sn = URLEncoder.encode(secondname, "utf-8");
LoadingDataURL client = new LoadingDataURL();
client.execute("https://domain.com/index.php?"+
"fristname=" + fn + "&secondname=" + sn);
Note: Don't encode the full url, just the parameter values.
I already got a method to read data from mysql and display it into my android app in textview's. The problem is that now I just retrieve all data from the database without doing a select ... where , just a select. I want to do a select ... where using the variables sent from my android app. I already use the folowing code in my login to send username and pass
nameValuePairs=new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("utilizator",utilizator.getText().toString().trim()));
nameValuePairs.add(new BasicNameValuePair("parola",parola.getText().toString().trim()));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
In the method I use I have 2 java files. I really don't understand them much ... so I don't know where to add the code to send variables to php.
httprequest.java
public class httprequest {
static int TIMEOUT = 5000;
public String read_url_resource(String _s_url)
{
String s_response_ = "";
BufferedReader br_reader=null;
StringBuilder sb_builder = new StringBuilder();
URL u_url = null;
try {
if ( _s_url==null || _s_url.length()==0)
return "";
//this.log_message("Downloading from "+_s_url, false);
u_url = new URL(_s_url);
HttpURLConnection huc_urlConnection = null;
huc_urlConnection = (HttpURLConnection)u_url.openConnection();
if ( huc_urlConnection!=null){
huc_urlConnection.setConnectTimeout(TIMEOUT);
huc_urlConnection.setReadTimeout(TIMEOUT);
huc_urlConnection.setUseCaches(false);
huc_urlConnection.setDoOutput(false);
InputStream is_input_stream = huc_urlConnection.getInputStream();
#SuppressWarnings("unused")
URL oURL = huc_urlConnection.getURL();
int i_response_code=huc_urlConnection.getResponseCode();
if ( i_response_code==200){
br_reader = new BufferedReader(new InputStreamReader(is_input_stream));
String line="";
while ((line = br_reader.readLine()) != null)
sb_builder.append(line);
is_input_stream.close();
s_response_ = sb_builder.toString();
String s_auth= huc_urlConnection.getURL().getAuthority();
}
}
} catch (Exception e) {
if ( e!=null )
Log.e("URL PROBLEM", e.toString());
s_response_ = "[\"error\": \"No connection\"]";
}
return s_response_;
}
}
and ReadJSONData.java
public class ReadJSONData extends AsyncTask<String, Integer, Integer> {
private String server = "http://asociatia-online.esy.es/cote.php?hc_location=ufi";
private ReadJSONListener jsonListener;
private String json ="";
private int internal_categ;
httprequest request;
public interface ReadJSONListener
{
void onTaskFinished(String s_json, int _i_internal_category);
}
public ReadJSONData (ReadJSONListener _jsonListener, int _i_internal_category)
{
this.jsonListener=_jsonListener;
this.internal_categ =_i_internal_category;
}
#Override
protected Integer doInBackground(String... strings) {
request = new httprequest();
this.downloadResource();
return null;
}
private void downloadResource() {
switch (this.internal_categ) {
case 1:
this.json = request.read_url_resource(server);
break;
}
}
#Override
protected void onPostExecute(Integer result)
{
this.jsonListener.onTaskFinished(this.json, this.internal_categ);
}
}
So, where to add the 4 lines code to send variables? In which file and where. Thanks !
With this code you can send variables to PHP and get some data back and store it in strings to use as you want.
private class ObtinereInformatii extends AsyncTask<String, Void, String>{
#Override
protected String doInBackground(String... params) {
//http post
try {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://asociatia-online.esy.es/rezumat.php");
nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("luna_rezumat",spinner_luna.getSelectedItem().toString().trim()));
nameValuePairs.add(new BasicNameValuePair("an_rezumat",spinner_an.getSelectedItem().toString().trim()));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
} catch (Exception e) {
Log.e("log_tag", "Error in http connection" + e.toString());
}
//convert response to string
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8);
sb = new StringBuilder();
sb.append(reader.readLine() + "\n");
String line = "0";
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
result = sb.toString();
Log.e("-------",result);
} catch (Exception e) {
Log.e("log_tag", "Error converting result " + e.toString());
}
return result;
}
protected void onPostExecute(String result){
try{
jArray = new JSONArray(result);
readJson(jArray);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
private void readJson(JSONArray ja_data) throws JSONException {
if (ja_data!=null)
{
for (int i = 0; i<ja_data.length(); i++)
{
JSONObject jo = ja_data.getJSONObject(i);
if (jo.has("data_rezumat"))
{
if (jo.getString("data_rezumat")!=null)
{
z_data_rezumat= jo.getString("data_rezumat");
}
}
}
}
}