This question already has answers here:
How can I fix 'android.os.NetworkOnMainThreadException'?
(66 answers)
Closed 8 years ago.
public class Foursquare {
private static final String LOGIN = "oauth";
public static final String API_END_POING_BASE_URL = "https://api.foursquare.com/v2/";
public static String REDIRECT_URI;
public static final String API_URL = "https://foursquare.com/oauth2/";
//public static final String CANCEL_URI = "";
public static final String TOKEN = "access_token";
public static final String EXPIRES = "expires_in";
public static final String SINGLE_SIGN_ON_DISABLED = "service_disabled";
public static String AUTHENTICATE_URL = "https://foursquare.com/oauth2/authenticate";// +
private String mClientId;
private String mClientSecret;
private String mAccessToken = null;
private DialogListener mAuthDialogListener;
public Foursquare(String clientId, String clientSecret, String redirectUrl) {
if (clientId == null || clientSecret == null) {
throw new IllegalArgumentException(
"You must specify your application ID when instantiating "
+ "a Foursquare object. See README for details.");
}
mClientId = clientId;
mClientSecret = clientSecret;
REDIRECT_URI = redirectUrl;
}
public void authorize(Activity activity, final DialogListener listener) {
mAuthDialogListener = listener;
startDialogAuth(activity);
}
public void startDialogAuth(Activity activity) {
CookieSyncManager.createInstance(activity);
Bundle params = new Bundle();
dialog(activity, LOGIN, params, new DialogListener() {
public void onComplete(Bundle values) {
// ensure any cookies set by the dialog are saved
CookieSyncManager.getInstance().sync();
String _token = values.getString(TOKEN);
setAccessToken(_token);
// setAccessExpiresIn(values.getString(EXPIRES));
if (isSessionValid()) {
Log.d("Foursquare-authorize",
"Login Success! access_token=" + getAccessToken());
mAuthDialogListener.onComplete(values);
} else {
mAuthDialogListener.onFoursquareError(new FoursquareError(
"Failed to receive access token."));
}
}
public void onError(DialogError error) {
Log.d("Foursquare-authorize", "Login failed: " + error);
mAuthDialogListener.onError(error);
}
public void onFoursquareError(FoursquareError error) {
Log.d("Foursquare-authorize", "Login failed: " + error);
mAuthDialogListener.onFoursquareError(error);
}
public void onCancel() {
Log.d("Foursquare-authorize", "Login canceled");
mAuthDialogListener.onCancel();
}
});
}
public void dialog(Context context, String action, Bundle parameters,
final DialogListener listener) {
String endpoint = "";
parameters.putString("client_id", mClientId);
parameters.putString("display", "touch");
if (action.equals(LOGIN)) {
endpoint = AUTHENTICATE_URL;
parameters.putString("client_secret", mClientSecret);
parameters.putString("response_type", "token");
parameters.putString("redirect_uri", REDIRECT_URI);
}
// if (isSessionValid()) {
// parameters.putString(TOKEN, getAccessToken());
// }
String url = endpoint + "?" + Util.encodeUrl(parameters);
if (context.checkCallingOrSelfPermission(Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED) {
Util.showAlert(context, "Error",
"Application requires permission to access the Internet");
} else {
new FoursquareDialog(context, url, listener).show();
}
}
public boolean isSessionValid() {
if (getAccessToken() != null) {
return true;
}
return false;
}
public void setAccessToken(String token) {
mAccessToken = token;
}
public String getAccessToken() {
return mAccessToken;
}
public String request(String graphPath) throws MalformedURLException,
IOException {
return request(graphPath, new Bundle(), "GET");
}
public String request(String graphPath, Bundle parameters)
throws MalformedURLException, IOException {
return request(graphPath, parameters, "GET");
}
public String request(String graphPath, Bundle params, String httpMethod)
throws FileNotFoundException, MalformedURLException, IOException {
params.putString("format", "json");
if (isSessionValid()) {
params.putString("oauth_token", getAccessToken());
}
String url = API_END_POING_BASE_URL + graphPath;
return Util.openUrl(url, httpMethod, params);
}
public static interface DialogListener {
/**
* Called when a dialog completes.
*
* Executed by the thread that initiated the dialog.
*
* #param values
* Key-value string pairs extracted from the response.
*/
public void onComplete(Bundle values);
/**
* Called when a Foursquare responds to a dialog with an error.
*
* Executed by the thread that initiated the dialog.
*
*/
public void onFoursquareError(FoursquareError e);
/**
* Called when a dialog has an error.
*
* Executed by the thread that initiated the dialog.
*
*/
public void onError(DialogError e);
/**
* Called when a dialog is canceled by the user.
*
* Executed by the thread that initiated the dialog.
*
*/
public void onCancel();
}
}
i am using foursqure functionality in my application in which user share any data so user can share on foursqure..,the problem is when i am using "StrictMode "functionality in my oncreate.,its not giving me error.,but when i am not using its giving me networkon minthread exception
i am getting this exception in foursqure.when dialog is loading??what i do plese help me thankyou...:)
here is my logcat
Networking operations tend to take some time. That's why on Android, it's forbidden to perform Networking Tasks on the UI (foreground) thread. The System throws a NetworkingOnMainThreadException if you try it.
You have to move your Networking code to a Background thread. The easiest way to do that is by using an AsyncTask.
Implement AsyncTask, read here
Related
public void signInWithLinkedIn(View view) {
//First check if user is already authenticated or not and session is valid or not
if (!LISessionManager.getInstance(this).getSession().isValid()) {
//if not valid then start authentication
LISessionManager.getInstance(getApplicationContext()).init(LinkedInActivity.this, buildScope()//pass the build scope here
, new AuthListener() {
#Override
public void onAuthSuccess() {
// Authentication was successful. You can now do
// other calls with the SDK.
Toast.makeText(LinkedInActivity.this, "Successfully authenticated with LinkedIn.", Toast.LENGTH_SHORT).show();
//on successful authentication fetch basic profile data of user
//LISessionManager.getInstance(getApplicationContext()).clearSession();
fetchBasicProfileData();
}
#Override
public void onAuthError(LIAuthError error) {
// Handle authentication errors
//LISessionManager.getInstance(getApplicationContext()).clearSession();
Log.e("AUTH ERROR", "Auth Error :" + error.toString());
Toast.makeText(LinkedInActivity.this, "Failed to authenticate with LinkedIn. Please try again.", Toast.LENGTH_SHORT).show();
}
}, true);//if TRUE then it will show dialog if
// any device has no LinkedIn app installed to download app else won't show anything
} else {
//LISessionManager.getInstance(getApplicationContext()).clearSession();
Toast.makeText(this, "You have already been authenticated.", Toast.LENGTH_SHORT).show();
//if user is already authenticated fetch basic profile data for user
fetchBasicProfileData();
}
}
private static Scope buildScope() {
//Check Scopes in Application Settings before passing here else you won't able to read that data
// Scope.R_CONTACTINFO
return Scope.build(Scope.R_BASICPROFILE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
LISessionManager.getInstance(getApplicationContext()).onActivityResult(this, requestCode, resultCode, data);
Log.d("Access token->", LISessionManager.getInstance(getApplicationContext()).getSession().getAccessToken().getValue());
}
/**
* method to fetch basic profile data
*/
private void fetchBasicProfileData() {
//In URL pass whatever data from user you want for more values check below link
//LINK : https://developer.linkedin.com/docs/fields/basic-profile
String url = "https://api.linkedin.com/v1/people/~:(id,first-name,last-name,headline,public-profile-url,picture-url,email-address,picture-urls::(original))";
APIHelper apiHelper = APIHelper.getInstance(getApplicationContext());
apiHelper.getRequest(this, url, new ApiListener() {
#Override
public void onApiSuccess(ApiResponse apiResponse) {
// Success!
JSONObject responseObject = apiResponse.getResponseDataAsJson();
try {
profileURL = responseObject.getString("publicProfileUrl");
imgURL = responseObject.getString("pictureUrl");
fetchConnectionsData();
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onApiError(LIApiError liApiError) {
// Error making GET request!
Log.e("FETCH PROFILE ERROR", "Fetch profile Error :" + liApiError.getLocalizedMessage());
Toast.makeText(LinkedInActivity.this, "Failed. Please try again.", Toast.LENGTH_SHORT).show();
}
});
}
Linkedin returns "No value for accessTokenValue" and "access toke is not set". It was working like last month but suddenly it does not work and I could not find anything wrong with the code. After much digging on Google, I am still unable to find a solution. Or am I using the v1 api which I should not? Any help will be greatly appreciated.
This is because the token generated by Linkedin SDK can not be verified by backend. The best solution is to open a webview and use Linkedin web apis- Step 1 - Create a new Class LinkedinActivity
public class LinkedinActivity {
/****FILL THIS WITH YOUR INFORMATION*********/
//This is the public api key of our application
private static final String API_KEY = "apikey";
//This is the private api key of our application
private static final String SECRET_KEY = "secretcode";
//This is any string we want to use. This will be used for avoiding CSRF attacks. You can generate one here: http://strongpasswordgenerator.com/
private static final String STATE = "123456789";
//This is the url that LinkedIn Auth process will redirect to. We can put whatever we want that starts with http:// or https:// .
//We use a made up url that we will intercept when redirecting. Avoid Uppercases.
private static final String REDIRECT_URI = "https://example.com";
/*********************************************/
//These are constants used for build the urls
private static final String AUTHORIZATION_URL = "https://www.linkedin.com/oauth/v2/authorization";
private static final String ACCESS_TOKEN_URL = "https://www.linkedin.com/uas/oauth2/accessToken";
private static final String SECRET_KEY_PARAM = "client_secret";
private static final String RESPONSE_TYPE_PARAM = "response_type";
private static final String GRANT_TYPE_PARAM = "grant_type";
private static final String GRANT_TYPE = "authorization_code";
private static final String RESPONSE_TYPE_VALUE = "code";
private static final String CLIENT_ID_PARAM = "client_id";
private static final String STATE_PARAM = "state";
private static final String REDIRECT_URI_PARAM = "redirect_uri";
/*---------------------------------------*/
private static final String QUESTION_MARK = "?";
private static final String AMPERSAND = "&";
private static final String EQUALS = "=";
private WebView webView;
private ImageView close_icon;
private ProgressDialog pd;
//private OauthInterface oauthInterface;
String accessToken;
Context context;
Dialog dialog;
public LinkedinActivity(#NonNull Context context) {
this.context = context;
}
public void showLinkedin() {
dialog = new Dialog(context, R.style.AppTheme);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
// dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
dialog.setContentView(R.layout.linkedin_activity);
dialog.setCancelable(false);
dialog.setCanceledOnTouchOutside(false);
pd = ProgressDialog.show(context, "", "Loading...", true);
dialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
#Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
LinkedinData linkedinData = (LinkedinData) context;
linkedinData.linkedCancel();
dialog.dismiss();
}
return true;
}
});
//oauthInterface = new OauthPresenter(this);
//get the webView from the layout
webView = (WebView) dialog.findViewById(R.id.activity_web_view);
close_icon = (ImageView) dialog.findViewById(R.id.close_icon);
close_icon.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
LinkedinData linkedinData = (LinkedinData) context;
linkedinData.linkedCancel();
dialog.dismiss();
}
});
//Request focus for the webview
webView.requestFocus(View.FOCUS_DOWN);
//Show a progress dialog to the user
//Set a custom web view client
webView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
//This method will be executed each time a page finished loading.
//The only we do is dismiss the progressDialog, in case we are showing any.
if (pd != null && pd.isShowing()) {
pd.dismiss();
}
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String authorizationUrl) {
//This method will be called when the Auth proccess redirect to our RedirectUri.
//We will check the url looking for our RedirectUri.
if (authorizationUrl.startsWith(REDIRECT_URI)) {
Log.i("Authorize", "");
Uri uri = Uri.parse(authorizationUrl);
//We take from the url the authorizationToken and the state token. We have to check that the state token returned by the Service is the same we sent.
//If not, that means the request may be a result of CSRF and must be rejected.
String stateToken = uri.getQueryParameter(STATE_PARAM);
if (stateToken == null || !stateToken.equals(STATE)) {
Log.e("Authorize", "State token doesn't match");
return true;
}
//If the user doesn't allow authorization to our application, the authorizationToken Will be null.
String authorizationToken = uri.getQueryParameter(RESPONSE_TYPE_VALUE);
if (authorizationToken == null) {
Log.i("Authorize", "The user doesn't allow authorization.");
return true;
}
Log.i("Authorize", "Auth token received: " + authorizationToken);
//Generate URL for requesting Access Token
String accessTokenUrl = getAccessTokenUrl(authorizationToken);
//We make the request in a AsyncTask
new PostRequestAsyncTask().execute(accessTokenUrl);
} else {
//Default behaviour
Log.i("Authorize", "Redirecting to: " + authorizationUrl);
webView.loadUrl(authorizationUrl);
}
return true;
}
});
//Get the authorization Url
String authUrl = getAuthorizationUrl();
Log.i("Authorize", "Loading Auth Url: " + authUrl);
//Load the authorization URL into the webView
webView.loadUrl(authUrl);
dialog.show();
}
private static String getAccessTokenUrl(String authorizationToken) {
return ACCESS_TOKEN_URL
+ QUESTION_MARK
+ GRANT_TYPE_PARAM + EQUALS + GRANT_TYPE
+ AMPERSAND
+ RESPONSE_TYPE_VALUE + EQUALS + authorizationToken
+ AMPERSAND
+ CLIENT_ID_PARAM + EQUALS + API_KEY
+ AMPERSAND
+ REDIRECT_URI_PARAM + EQUALS + REDIRECT_URI
+ AMPERSAND
+ SECRET_KEY_PARAM + EQUALS + SECRET_KEY;
}
/**
* Method that generates the url for get the authorization token from the Service
*
* #return Url
*/
private static String getAuthorizationUrl() {
return AUTHORIZATION_URL
+ QUESTION_MARK + RESPONSE_TYPE_PARAM + EQUALS + RESPONSE_TYPE_VALUE
+ AMPERSAND + CLIENT_ID_PARAM + EQUALS + API_KEY
+ AMPERSAND + REDIRECT_URI_PARAM + EQUALS + REDIRECT_URI
+ AMPERSAND + STATE_PARAM + EQUALS + STATE
+ AMPERSAND + "scope=r_emailaddress";
}
private class PostRequestAsyncTask extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute() {
pd = ProgressDialog.show(context, "", "loading", true);
}
#Override
protected String doInBackground(String... urls) {
if (urls.length > 0) {
String url = urls[0];
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpost = new HttpPost(url);
try {
HttpResponse response = httpClient.execute(httpost);
if (response != null) {
//If status is OK 200
if (response.getStatusLine().getStatusCode() == 200) {
String result = EntityUtils.toString(response.getEntity());
//Convert the string result to a JSON Object
JSONObject resultJson = new JSONObject(result);
//Extract data from JSON Response
int expiresIn = resultJson.has("expires_in") ? resultJson.getInt("expires_in") : 0;
accessToken = resultJson.has("access_token") ? resultJson.getString("access_token") : null;
Log.e("Tokenm", "" + accessToken);
if (expiresIn > 0 && accessToken != null) {
Log.i("Authorize", "This is the access Token: " + accessToken + ". It will expires in " + expiresIn + " secs");
//Calculate date of expiration
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.SECOND, expiresIn);
long expireDate = calendar.getTimeInMillis();
////Store both expires in and access token in shared preferences
SharedPreferences preferences = context.getSharedPreferences("user_info", 0);
SharedPreferences.Editor editor = preferences.edit();
editor.putLong("expires", expireDate);
editor.putString("accessToken", accessToken);
//oauthInterface.oauthAuthentication(accessToken, "linkedin", new HackedPrefence(getApplicationContext()).getDevice_token());
editor.commit();
return accessToken;
}
}
}
} catch (IOException e) {
Log.e("Authorize", "Error Http response " + e.getLocalizedMessage());
} catch (ParseException e) {
Log.e("Authorize", "Error Parsing Http response " + e.getLocalizedMessage());
} catch (JSONException e) {
Log.e("Authorize", "Error Parsing Http response " + e.getLocalizedMessage());
}
}
return accessToken;
}
#Override
protected void onPostExecute(String status) {
if (pd != null && pd.isShowing()) {
pd.dismiss();
}
LinkedinData linkedinData = (LinkedinData) context;
linkedinData.LinkedinSuccess(status);
if (dialog.isShowing()) {
dialog.dismiss();
}
}
}
interface LinkedinData {
void linkedCancel();
void LinkedinSuccess(String Token);
}
}
Step 2 - Call LinkdinActivity.java class using the following code
new LinkedinActivity(this).showLinkedin();
You can call the above code on the click of a button. Example
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
new LinkedinActivity(this).showLinkedin();
}
});
Here is linkedin_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="#+id/activity_web_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView
android:id="#+id/close_icon"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginRight="10dp"
android:layout_marginTop="22dp"
android:src="#drawable/ic_close_black"
android:layout_alignParentRight="true"/>
</RelativeLayout>
I have a project: myApp
these files...
- myFragment.java.
- myDialogFragment.java.
- myAsyncTask.java
I have a project: myLibrary
This project "is Library" of "myApp"
I have...
- myMethodsToUpload.java
One of these methods, have a While bucle for write the file on php server.
Everything works like magic! :)
and the reason for the file structure is to make the library reusable.
but...
How can I send the increments of a value inside of this While bucle, to myAsyncTask.java?
Considering that...
what I want to do... is to make "myMethodsToUpload.java", reusable.
Some code...
myFragment.java
myDialogFragment df = new myDialogFragment();
df.setMyThings(new myAsynctask(), myParameters);
df.setTargetFragment(this, 0);
df.show(getFragmentManager(), DIALOG_FRAGMENT_TAG);
.
myDialogFragment.java
public class myDialogFragment extends DialogFragment {
myAsyncTask async;
public void setMyThings(myAsynctask inAsynctask, String[] inArray){
async = inAsynctask;
async.sendFragment(this);
parameters = inArray;
}
//...
//Only called from "myAsyncTask.java"
public void updateFromAsyncTask(Integer porcent){
progressbar.setProgress(porcent);
}
//...
}
.
myAsyncTask.java
public class myAsynctask extends AsyncTask<String, Integer, String> {
void sendFragment(myDialogFrament inFragment){
myDialogFrament = inFragment;
}
//...
#Override
protected String doInBackground(String... inArray) {
String urlPHP = inArray[0];
String pathImg = inArray[1];
String paramValue = inArray[2];
String msj = "";
try {
methodsToUpload up = new methodsToUpload(urlPHP);
up.connectNow();
up.insertFile(pathImg);
up.insertParams("pName", paramValue);
up.insertFinish();
msj = up.coonectClose();
} catch (Exception e) {
e.printStackTrace();
}
return msj;
}
//Called from "myMethods.java"
public void updateFromAsyncTask(int porcent){
publishProgress(porcent);
}
#Override
protected void onProgressUpdate(Integer... inPorcent) {
if(myDialogFragment == null){
return;
}
myDialogFragment.updateFromAsyncTask(inPorcent[0]);
}
}
.
myMethodsToUpload.java
public class myMethodsToUpload {
//...
public myMethodsToUpload(String url_in){
this.url = url_in;
}
public void insertFile(String path) throws Exception {
//...
//...
while (bytesRead > 0) {
salidaStream.write(buffer, 0, bufferSize);
sendedPorcent += bytesRead;
completedPorcent = (int) (sendedPorcent * 100 / fileSize);
//This line doesn't work...
//because myAsyncTask.java, is in another project.
myAsyncTask.updateFromAsyncTask(completedPorcent);
bytesAvailable = archivoStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = archivoStream.read(buffer, 0, bufferSize);
}
//...
//...
}
}
.
I've already tried...
"MyLibrary" -> propeties -> java build path -> projects -> add -> Project(myApp)
but...
throws me errors:
W/System.err(32469): at java.util.concurrent.FutureTask.run(FutureTask.java:237)...
ThreadPoolExecutor.runworker...
etc.
And, in the status bar of eclipse appears every moment "Building Workspace (X%)"
I'm a newbie, but I think the error happens because "MyLibrary" is Library of "MyApp", and I'm trying use "java build path".
So... how can I resolve this?, I'm lost!!!
sorry by my english... thanks in advance! :)
Here is a simple exemple :
Your AsyncTask class :
private CallBack mCallback;
public static interface CallBack {
public void updateValue(int value);
}
public void setCallBack(CallBack callBack){
this.mCallBack = callBack;
}
#Override
protected void onProgressUpdate(Integer... inPorcent) {
mCallback.updateValue(inPorcent[0].intValue());
}
Your fragment class :
public class Fragment extends Fragment implements Callback {
private AsyncTask yourAsyncTask;
...
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
yourAsyncTask = new AsyncTask();
yourAsyncTask.setCallBack(this);
yourAsyncTask.excecute();
}
#Override
public void updateValue(int value){
Log.e(TAG,"Value : " + value);
}
}
EDIT 1 :
public class AdsHttpRequest {
private static final String TAG = AdsHttpRequest.class.getSimpleName(); // log
private GetHttpTask mGetAsyncTask;
private static AdsHttpRequest mInstance;
private OnGetRequestListener mCallBack;
private static final String SUCCESS = "success";
private static final String SUCCES = "succes";
private static final String FAILED = "fail";
/**
* #return a singleton instance of {#link AdsHttpRequest}
*/
public static AdsHttpRequest getInstance() {
if (mInstance == null) {
synchronized (AdsHttpRequest.class) {
if (mInstance == null) {
mInstance = new AdsHttpRequest();
}
}
}
return mInstance;
}
/**
* Initialize the {#link AsyncTask}, set the callback, execute the task
*
* #param url
* url for the request
* #param callback
* {#link OnGetRequestListener} for feed back
*/
public void post(String url, OnGetRequestListener callback) {
mCallBack = callback;
if (mGetAsyncTask == null) {
mGetAsyncTask = new GetHttpTask();
} else {
cancelGetTask();
mGetAsyncTask = new GetHttpTask();
}
mGetAsyncTask.execute(url);
}
/**
* cancel the {#link AsyncTask} if it's still alive <br>
* <b>see </b> {#link Status}
*/
public void cancelGetTask() {
if (mGetAsyncTask != null && mGetAsyncTask.getStatus().equals(Status.RUNNING)) {
mGetAsyncTask.cancel(true);
}
mGetAsyncTask = null;
}
private AdsHttpRequest() {
super();
}
/**
* Actually construct and launch the HTTP request
*
* #param url
* url of the request
* #return response of the server
*/
private String getResponseFromUrl(String url) {
String xml = null;
try {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
HttpResponse httpResponse = httpClient.execute(httpGet);
HttpEntity httpEntity = httpResponse.getEntity();
xml = EntityUtils.toString(httpEntity);
} catch (Exception e) {
Log.e(TAG, "", e);
}
return xml;
}
/**
* Manage the http request in background
*
* #param String
* url for the request
*/
private class GetHttpTask extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... params) {
if (params[0] != null) {
return getResponseFromUrl(params[0]); // return the response of the server
}
return null;
}
#Override
protected void onPostExecute(String result) {
if (result != null) {
if (result.contains(SUCCES) || result.contains(SUCCESS)) {
mCallBack.onGetRequestResult(SUCCESS);
} else {
mCallBack.onGetRequestResult(FAILED);
}
}
}
}
}
The way that I'm doing this consume more memory, time, threads? (I'm guessing)
I am trying to allow Android users to post to their Tumblr blogs using my app. I am able to launch Tumblr, enter my username and password, and log in, however the problem is the Access Token I receive appears to be invalid (I get a 401 - Unauthorized when I use it with any of Tumblr's API calls).
Below is the code I am using. I am able to authenticate with Twitter, but Tumblr is giving me difficulties. If anyone has any ideas, suggestions, or improvements, they would be much appreciated. Thanks!
public final class TumblrWebView extends Activity {
private final String TAG = getClass().getSimpleName();
OAuth10Service service;
public final static String PARAMETER_CONSUMER_KEY = "CONSUMER_KEY";
public final static String PARAMETER_CONSUMER_SECRET = "CONSUMER_SECRET";
public final static String PARAMETER_CALLBACK_URL = "CALLBACK_URL";
private String consumerKey;
private String consumerSecret;
private String callbackUrl;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.web_view);
/*
* Get params
*/
Intent intent = getIntent();
consumerKey = intent.getStringExtra(PARAMETER_CONSUMER_KEY);
consumerSecret = intent.getStringExtra(PARAMETER_CONSUMER_SECRET);
callbackUrl = intent.getStringExtra(PARAMETER_CALLBACK_URL);
service = OAuthService.newInstance(new TumblrApi(), consumerKey, consumerSecret, new OAuth10ServiceCallback() {
#Override
public void onOAuthAccessTokenReceived(OAuth10Token token) {
complete(token);
Log.i(TAG, "Access token recieved");
// System.out.println("token recieved " + token.getAccessToken());
// System.out.println("token recieved " + token.getUserSecret());
}
#Override
public void onOAuthRequestTokenReceived() {
loadWebView();
Log.i(TAG, "Request token recieved");
}
#Override
public void onOAuthRequestTokenFailed(HootResult result) {
Log.e(TAG, "Token request failed " + result.getException());
}
#Override
public void onOAuthAccessTokenFailed(HootResult result) {
Log.e(TAG, "Token access failed " + result);
}
});
service.start();
}
#SuppressLint("SetJavaScriptEnabled")
private void loadWebView() {
final WebView webview = (WebView) findViewById(R.id.web_view);
webview.getSettings().setJavaScriptEnabled(true);
webview.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// Checking for our successful callback
if(url.startsWith(callbackUrl)) {
webview.setVisibility(View.GONE);
Log.d(TAG, "token url " + url + " " + service.getOAuthAccessToken(url));
} else {
Log.d(TAG, "token url");
}
return super.shouldOverrideUrlLoading(view, url);
}
});
webview.loadUrl(service.getAuthorizeUrl());
}
private void complete(OAuth10Token token) {
Intent resultIntent = new Intent();
resultIntent.putExtra(TumblrUtils.PREF_TUMBLR_ACCESS, token.getAccessToken());
resultIntent.putExtra(TumblrUtils.PREF_TUMBLR_SECRET, token.getUserSecret());
setResult(RESULT_OK, resultIntent);
finish();
}
}
EDIT: A helper class
public class TumblrUtils {
// Consumer Key and Secret
private static final String TUMBLR_CONSUMER_KEY = "{ ENTER TUMBLR CONSUMER KEY }";
private static final String TUMBLR_CONSUMER_SECRET = "{ ENTER TUMBLR CONSUMER SECRET }";
// Callback URL
private static final String TUMBLR_CALLBACK_URL = "http://example.com";
// Request Code
public static final int TUMBLR_REQUEST_CODE = 87; /* 87 - TR */
// Preference Constants
public static final String PREF_TUMBLR_USER = "tumblr_user";
public static final String PREF_TUMBLR_ACCESS = "tumblr_access_token";
public static final String PREF_TUMBLR_SECRET = "tumblr_secret_token";
public static final String TUMBLR_REQUEST_URL = "http://www.tumblr.com/oauth/request_token";
public static final String TUMBLR_ACCESS_URL = "http://www.tumblr.com/oauth/access_token";
public static final String TUMBLR_AUTHORIZE_URL = "http://www.tumblr.com/oauth/authorize";
private static OAuthConsumer tumblrConsumer;
private static String tumblrHost;
private static String tumblrToken;
private static String tumblrTokenSecret;
private static String getConsumerKey() {
return TUMBLR_CONSUMER_KEY;
}
private static String getConsumerSecret() {
return TUMBLR_CONSUMER_SECRET;
}
private static String getCallbackUrl() {
return TUMBLR_CALLBACK_URL;
}
public static String getRequestUrl() {
return TUMBLR_REQUEST_URL;
}
public static String getAccessUrl() {
return TUMBLR_ACCESS_URL;
}
public static String getAuthorizeUrl() {
return TUMBLR_AUTHORIZE_URL;
}
public static OAuthConsumer getTumblrConsumer() {
return tumblrConsumer;
}
public static String getTumblrHost() {
return tumblrHost;
}
public static void setTumblrHost(String host) {
TumblrUtils.tumblrHost = host;
}
public static String getTumblrToken() {
return tumblrToken;
}
public static String getTumblrTokenSecret() {
return tumblrTokenSecret;
}
public static Intent getTumblrIntent(Context activity) {
Intent TumblrIntent = new Intent(activity, TumblrWebView.class);
TumblrIntent.putExtra("CONSUMER_KEY", getConsumerKey());
TumblrIntent.putExtra("CONSUMER_SECRET", getConsumerSecret());
TumblrIntent.putExtra("CALLBACK", getCallbackUrl());
return TumblrIntent;
}
public static OAuthConsumer saveTumblrResult(SharedPreferences settings,
String access_token, String secret_token) {
Editor editor = settings.edit();
editor.putString(PREF_TUMBLR_ACCESS, access_token);
editor.putString(PREF_TUMBLR_SECRET, secret_token);
editor.commit();
return saveTumblrResult(access_token, secret_token);
}
public static OAuthConsumer saveTumblrResult(String stringExtra1, String stringExtra2) {
tumblrToken = (stringExtra1);
tumblrTokenSecret = (stringExtra2);
tumblrConsumer = new CommonsHttpOAuthConsumer(
getConsumerKey(), getConsumerSecret());
tumblrConsumer.setTokenWithSecret(
tumblrToken, tumblrTokenSecret);
return tumblrConsumer;
}
}
EDIT: TumblrWebActivity - startActivityForResult
startActivityForResult(
TumblrUtils.getTumblrIntent(Settings_ShareSettings.this),
EDIT: TumblrWebActivity - onActivityResult
TumblrUtils.TUMBLR_REQUEST_CODE);
TumblrUtils.saveTumblrResult(mPrefs,
data.getStringExtra(TumblrUtils.PREF_TUMBLR_ACCESS),
data.getStringExtra(TumblrUtils.PREF_TUMBLR_SECRET));
new TumblrTask("https://api.tumblr.com/v2/user/info").execute();
EDIT: GetUserInfo - AsyncTask
private final class TumblrTask extends AsyncTask<String, Void, String> {
String url;
public TumblrTask(String url) {
this.url = url;
}
#Override
protected String doInBackground(String... params) {
String result = "";
HttpClient httpclient = GlobalContext.getHttpClient();
HttpRequestBase request = new HttpGet(url);
try {
TumblrUtils.getTumblrConsumer().sign(request);
} catch (OAuthMessageSignerException e) {
e.printStackTrace();
} catch (OAuthExpectationFailedException e) {
e.printStackTrace();
} catch (OAuthCommunicationException e) {
e.printStackTrace();
}
try {
HttpResponse response = httpclient.execute(request, GlobalContext.getLocalContext());
HttpEntity entity = response.getEntity();
InputStream instream = entity.getContent();
result = GlobalContext.convertStreamToString(instream);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
#Override
protected void onPostExecute(String result) {
try {
JSONObject jObject = new JSONObject(result.trim());
System.out.println(jObject);
if(jObject.has("response")) {
JSONObject jResponse = jObject.getJSONObject("response");
System.out.println(jResponse);
if(jResponse.has("user")) {
JSONObject jUser = jResponse.getJSONObject("user");
System.out.println(jUser);
tumblr_name = jUser.getString("name");
TumblrUtils.saveTumblrResult(mPrefs, tumblr_name);
tvTumblr.setText(tumblr_name);
ibTumblr.setSelected(true);
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
EDIT: NOTE: Requires AndrOAuth
As it turns out, the Access Token and Access Token Secret returned were valid. The problem was that I was not signing the request with the Access Token Secret.
what is the procedure to login throw twitter api1.1.
i have used old api that will show me twitter connection failed because of api 1 is deprecated.
private final TwDialogListener mTwLoginDialogListener = new TwDialogListener()
{
public void onComplete(String value)
{
getTwitterDetail();
}
public void onError(String value) {
Toast.makeText(LoginActivity.this, "Twitter connection failed", Toast.LENGTH_LONG).show();
}
};
LOG
{"errors": [{"message": "The Twitter REST API v1 is no longer active.
Please migrate to API v1.1. https://dev.twitter.com/docs/api/1.1/overview.", "code": 68}]}
As you see from error log API v.1 is no longer active and everybody must migrate to v1.1. In API v1.1. you must log in via OAUTH to get connected. So you also have to register your app on dev.twitter.com.
You can find below example here
public class Main extends Activity{
public static final String TAG = Main.class.getSimpleName();
public static final String TWITTER_OAUTH_REQUEST_TOKEN_ENDPOINT = "..."; //cannot share more then 2 lins, sorry
public static final String TWITTER_OAUTH_ACCESS_TOKEN_ENDPOINT = "...";
public static final String TWITTER_OAUTH_AUTHORIZE_ENDPOINT = "...";
private CommonsHttpOAuthProvider commonsHttpOAuthProvider;
private CommonsHttpOAuthConsumer commonsHttpOAuthConsumer;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
commonsHttpOAuthProvider = new CommonsHttpOAuthProvider(TWITTER_OAUTH_REQUEST_TOKEN_ENDPOINT,
TWITTER_OAUTH_ACCESS_TOKEN_ENDPOINT, TWITTER_OAUTH_AUTHORIZE_ENDPOINT);
commonsHttpOAuthConsumer = new CommonsHttpOAuthConsumer(getString(R.string.twitter_oauth_consumer_key),
getString(R.string.twitter_oauth_consumer_secret));
commonsHttpOAuthProvider.setOAuth10a(true);
TwDialog dialog = new TwDialog(this, commonsHttpOAuthProvider, commonsHttpOAuthConsumer,
dialogListener, R.drawable.android);
dialog.show();
}
private Twitter.DialogListener dialogListener = new Twitter.DialogListener() {
public void onComplete(Bundle values) {
String secretToken = values.getString("secret_token");
Log.i(TAG,"secret_token=" + secretToken);
String accessToken = values.getString("access_token");
Log.i(TAG,"access_token=" + accessToken);
new Tweeter(accessToken,secretToken).tweet(
"Tweet from sample Android OAuth app. unique code: " + System.currentTimeMillis());
}
public void onTwitterError(TwitterError e) { Log.e(TAG,"onTwitterError called for TwitterDialog",
new Exception(e)); }
public void onError(DialogError e) { Log.e(TAG,"onError called for TwitterDialog", new Exception(e)); }
public void onCancel() { Log.e(TAG,"onCancel"); }
};
public static final Pattern ID_PATTERN = Pattern.compile(".*?\"id_str\":\"(\\d*)\".*");
public static final Pattern SCREEN_NAME_PATTERN = Pattern.compile(".*?\"screen_name\":\"([^\"]*).*");
public class Tweeter {
protected CommonsHttpOAuthConsumer oAuthConsumer;
public Tweeter(String accessToken, String secretToken) {
oAuthConsumer = new CommonsHttpOAuthConsumer(getString(R.string.twitter_oauth_consumer_key),
getString(R.string.twitter_oauth_consumer_secret));
oAuthConsumer.setTokenWithSecret(accessToken, secretToken);
}
public boolean tweet(String message) {
if (message == null && message.length() > 140) {
throw new IllegalArgumentException("message cannot be null and must be less than 140 chars");
}
// create a request that requires authentication
try {
HttpClient httpClient = new DefaultHttpClient();
Uri.Builder builder = new Uri.Builder();
builder.appendPath("statuses").appendPath("update.json")
.appendQueryParameter("status", message);
Uri man = builder.build();
HttpPost post = new HttpPost("http://twitter.com" + man.toString());
oAuthConsumer.sign(post);
HttpResponse resp = httpClient.execute(post);
String jsonResponseStr = convertStreamToString(resp.getEntity().getContent());
Log.i(TAG,"response: " + jsonResponseStr);
String id = getFirstMatch(ID_PATTERN,jsonResponseStr);
Log.i(TAG,"id: " + id);
String screenName = getFirstMatch(SCREEN_NAME_PATTERN,jsonResponseStr);
Log.i(TAG,"screen name: " + screenName);
final String url = MessageFormat.format("https://twitter.com/#!/{0}/status/{1}",screenName,id);
Log.i(TAG,"url: " + url);
Runnable runnable = new Runnable() {
public void run() {
((TextView)Main.this.findViewById(R.id.textView)).setText("Tweeted: " + url);
}
};
Main.this.runOnUiThread(runnable);
return resp.getStatusLine().getStatusCode() == 200;
} catch (Exception e) {
Log.e(TAG,"trying to tweet: " + message, e);
return false;
}
}
}
public static String convertStreamToString(java.io.InputStream is) {
try {
return new java.util.Scanner(is).useDelimiter("\\A").next();
} catch (java.util.NoSuchElementException e) {
return "";
}
}
public static String getFirstMatch(Pattern pattern, String str){
Matcher matcher = pattern.matcher(str);
if(matcher.matches()){
return matcher.group(1);
}
return null;
}
I use this sample to login Twitter, post status and photo. I used it for a long time. Now Twitter requires upgrading from Twitter API 1.0 to Twitter API 1.1. What do I have to do to upgrade it? I tried to replace the old lib with this lib and there is no problem so far but I'm scared of I didn't do the change completely.
You must log in via OAUTH (https://dev.twitter.com/docs/auth/using-oauth) to get connected. So you also have to register your app on dev.twitter.com.
You can find below example here https://github.com/browep/Android-OAuth-Twitter-Example.
public class Main extends Activity{
public static final String TAG = Main.class.getSimpleName();
public static final String TWITTER_OAUTH_REQUEST_TOKEN_ENDPOINT = "..."; //cannot share more then 2 lins, sorry
public static final String TWITTER_OAUTH_ACCESS_TOKEN_ENDPOINT = "...";
public static final String TWITTER_OAUTH_AUTHORIZE_ENDPOINT = "...";
private CommonsHttpOAuthProvider commonsHttpOAuthProvider;
private CommonsHttpOAuthConsumer commonsHttpOAuthConsumer;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
commonsHttpOAuthProvider = new CommonsHttpOAuthProvider(TWITTER_OAUTH_REQUEST_TOKEN_ENDPOINT,
TWITTER_OAUTH_ACCESS_TOKEN_ENDPOINT, TWITTER_OAUTH_AUTHORIZE_ENDPOINT);
commonsHttpOAuthConsumer = new CommonsHttpOAuthConsumer(getString(R.string.twitter_oauth_consumer_key),
getString(R.string.twitter_oauth_consumer_secret));
commonsHttpOAuthProvider.setOAuth10a(true);
TwDialog dialog = new TwDialog(this, commonsHttpOAuthProvider, commonsHttpOAuthConsumer,
dialogListener, R.drawable.android);
dialog.show();
}
private Twitter.DialogListener dialogListener = new Twitter.DialogListener() {
public void onComplete(Bundle values) {
String secretToken = values.getString("secret_token");
Log.i(TAG,"secret_token=" + secretToken);
String accessToken = values.getString("access_token");
Log.i(TAG,"access_token=" + accessToken);
new Tweeter(accessToken,secretToken).tweet(
"Tweet from sample Android OAuth app. unique code: " + System.currentTimeMillis());
}
public void onTwitterError(TwitterError e) { Log.e(TAG,"onTwitterError called for TwitterDialog",
new Exception(e)); }
public void onError(DialogError e) { Log.e(TAG,"onError called for TwitterDialog", new Exception(e)); }
public void onCancel() { Log.e(TAG,"onCancel"); }
};
public static final Pattern ID_PATTERN = Pattern.compile(".*?\"id_str\":\"(\\d*)\".*");
public static final Pattern SCREEN_NAME_PATTERN = Pattern.compile(".*?\"screen_name\":\"([^\"]*).*");
public class Tweeter {
protected CommonsHttpOAuthConsumer oAuthConsumer;
public Tweeter(String accessToken, String secretToken) {
oAuthConsumer = new CommonsHttpOAuthConsumer(getString(R.string.twitter_oauth_consumer_key),
getString(R.string.twitter_oauth_consumer_secret));
oAuthConsumer.setTokenWithSecret(accessToken, secretToken);
}
public boolean tweet(String message) {
if (message == null && message.length() > 140) {
throw new IllegalArgumentException("message cannot be null and must be less than 140 chars");
}
// create a request that requires authentication
try {
HttpClient httpClient = new DefaultHttpClient();
Uri.Builder builder = new Uri.Builder();
builder.appendPath("statuses").appendPath("update.json")
.appendQueryParameter("status", message);
Uri man = builder.build();
HttpPost post = new HttpPost("http://twitter.com" + man.toString());
oAuthConsumer.sign(post);
HttpResponse resp = httpClient.execute(post);
String jsonResponseStr = convertStreamToString(resp.getEntity().getContent());
Log.i(TAG,"response: " + jsonResponseStr);
String id = getFirstMatch(ID_PATTERN,jsonResponseStr);
Log.i(TAG,"id: " + id);
String screenName = getFirstMatch(SCREEN_NAME_PATTERN,jsonResponseStr);
Log.i(TAG,"screen name: " + screenName);
final String url = MessageFormat.format("https://twitter.com/#!/{0}/status/{1}",screenName,id);
Log.i(TAG,"url: " + url);
Runnable runnable = new Runnable() {
public void run() {
((TextView)Main.this.findViewById(R.id.textView)).setText("Tweeted: " + url);
}
};
Main.this.runOnUiThread(runnable);
return resp.getStatusLine().getStatusCode() == 200;
} catch (Exception e) {
Log.e(TAG,"trying to tweet: " + message, e);
return false;
}
}
}
public static String convertStreamToString(java.io.InputStream is) {
try {
return new java.util.Scanner(is).useDelimiter("\\A").next();
} catch (java.util.NoSuchElementException e) {
return "";
}
}
public static String getFirstMatch(Pattern pattern, String str){
Matcher matcher = pattern.matcher(str);
if(matcher.matches()){
return matcher.group(1);
}
return null;
}