Friday, 30 December 2011

How to Integrate Twitter in Android Application?

Create New Project & Add Following Code to Your MainActivity.java File:-

MainActivity.java

    private TwitterApp mTwitter;
    private static final String CONSUMER_KEY = "your consumer key";
    private static final String CONSUMER_SECRET = "your consumer secret key";

    private enum FROM {
        TWITTER_POST, TWITTER_LOGIN
    };

    private enum MESSAGE {
        SUCCESS, DUPLICATE, FAILED, CANCELLED
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mTwitter = new TwitterApp(this, CONSUMER_KEY, CONSUMER_SECRET);
    }

    public void onClick(View v) {
        mTwitter.setListener(mTwLoginDialogListener);
        mTwitter.resetAccessToken();
        if (mTwitter.hasAccessToken() == true) {
            try {
                mTwitter.updateStatus(TwitterApp.MESSAGE);
                postAsToast(FROM.TWITTER_POST, MESSAGE.SUCCESS);
            } catch (Exception e) {
                if (e.getMessage().toString().contains("duplicate")) {
                    postAsToast(FROM.TWITTER_POST, MESSAGE.DUPLICATE);
                }
                e.printStackTrace();
            }
            mTwitter.resetAccessToken();
        } else {
            mTwitter.authorize();
        }
    }

    private void postAsToast(FROM twitterPost, MESSAGE success) {
        switch (twitterPost) {
        case TWITTER_LOGIN:
            switch (success) {
            case SUCCESS:
                Toast.makeText(this, "Login Successful", Toast.LENGTH_LONG)
                        .show();
                break;
            case FAILED:
                Toast.makeText(this, "Login Failed", Toast.LENGTH_LONG).show();
            default:
                break;
            }
            break;
        case TWITTER_POST:
            switch (success) {
            case SUCCESS:
                Toast.makeText(this, "Posted Successfully", Toast.LENGTH_LONG)
                        .show();
                break;
            case FAILED:
                Toast.makeText(this, "Posting Failed", Toast.LENGTH_LONG)
                        .show();
                break;
            case DUPLICATE:
                Toast.makeText(this,
                        "Posting Failed because of duplicate message...",
                        Toast.LENGTH_LONG).show();
            default:
                break;
            }
            break;
        }
    }

    private TwDialogListener mTwLoginDialogListener = new TwDialogListener() {

        @Override
        public void onError(String value) {
            postAsToast(FROM.TWITTER_LOGIN, MESSAGE.FAILED);
            Log.e("TWITTER", value);
            mTwitter.resetAccessToken();
        }

        @Override
        public void onComplete(String value) {
            try {
                mTwitter.updateStatus(TwitterApp.MESSAGE);
                postAsToast(FROM.TWITTER_POST, MESSAGE.SUCCESS);
            } catch (Exception e) {
                if (e.getMessage().toString().contains("duplicate")) {
                    postAsToast(FROM.TWITTER_POST, MESSAGE.DUPLICATE);
                }
                e.printStackTrace();
            }
            mTwitter.resetAccessToken();
        }
    };


Add Following 3 Class into New Package "com.twitter.android"

Class 1:-(TwitterApp.java)

package com.twitter.android;

import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import oauth.signpost.OAuthProvider;
import oauth.signpost.basic.DefaultOAuthProvider;
import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.User;
import twitter4j.http.AccessToken;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Handler;
import android.os.Message;
import android.view.Window;

public class TwitterApp {
    private Twitter mTwitter;
    private TwitterSession mSession;
    private AccessToken mAccessToken;
    private CommonsHttpOAuthConsumer mHttpOauthConsumer;
    private OAuthProvider mHttpOauthprovider;
    private String mConsumerKey;
    private String mSecretKey;
    private ProgressDialog mProgressDlg;
    private TwDialogListener mListener;
    private Activity context;
    public static final String  OAUTH_CALLBACK_SCHEME   = "x-oauthflow-twitter";
    public static final String  OAUTH_CALLBACK_HOST     = "callback";
    public static final String  CALLBACK_URL      = OAUTH_CALLBACK_SCHEME + "://" + OAUTH_CALLBACK_HOST;
    private static final String TWITTER_ACCESS_TOKEN_URL = "https://api.twitter.com/oauth/access_token";
    private static final String TWITTER_AUTHORZE_URL = "https://api.twitter.com/oauth/authorize";
    private static final String TWITTER_REQUEST_URL = "https://api.twitter.com/oauth/request_token";
    public static final String MESSAGE = "Hello Everyone....from Dipak Keshariya";

    public TwitterApp(Activity context, String consumerKey, String secretKey) {
        this.context = context;

        mTwitter = new TwitterFactory().getInstance();
        mSession = new TwitterSession(context);
        mProgressDlg = new ProgressDialog(context);

        mProgressDlg.requestWindowFeature(Window.FEATURE_NO_TITLE);

        mConsumerKey = consumerKey;
        mSecretKey = secretKey;

        mHttpOauthConsumer = new CommonsHttpOAuthConsumer(mConsumerKey,
                mSecretKey);
       
        String request_url=TWITTER_REQUEST_URL;
        String access_token_url=TWITTER_ACCESS_TOKEN_URL;
        String authorize_url=TWITTER_AUTHORZE_URL;
       
        mHttpOauthprovider = new DefaultOAuthProvider(
                request_url,
                access_token_url,
                authorize_url);
        mAccessToken = mSession.getAccessToken();

        configureToken();
    }

    public void setListener(TwDialogListener listener) {
        mListener = listener;
    }

    @SuppressWarnings("deprecation")
    private void configureToken() {
        if (mAccessToken != null) {
            mTwitter.setOAuthConsumer(mConsumerKey, mSecretKey);
            mTwitter.setOAuthAccessToken(mAccessToken);
        }
    }

    public boolean hasAccessToken() {
        return (mAccessToken == null) ? false : true;
    }

    public void resetAccessToken() {
        if (mAccessToken != null) {
            mSession.resetAccessToken();

            mAccessToken = null;
        }
    }

    public String getUsername() {
        return mSession.getUsername();
    }

    public void updateStatus(String status) throws Exception {
        try {
            mTwitter.updateStatus(status);
            // File f = new File("/mnt/sdcard/74.jpg");
           // mTwitter.updateProfileImage(f);
        } catch (TwitterException e) {
            throw e;
        }
    }

    public void authorize() {
        mProgressDlg.setMessage("Initializing ...");
        mProgressDlg.show();

        new Thread() {
            @Override
            public void run() {
                String authUrl = "";
                int what = 1;

                try {
                    authUrl = mHttpOauthprovider.retrieveRequestToken(
                            mHttpOauthConsumer, CALLBACK_URL);
                    what = 0;
                } catch (Exception e) {
                    e.printStackTrace();
                }
                mHandler.sendMessage(mHandler
                        .obtainMessage(what, 1, 0, authUrl));
            }
        }.start();
    }

    public void processToken(String callbackUrl) {
        mProgressDlg.setMessage("Finalizing ...");
        mProgressDlg.show();

        final String verifier = getVerifier(callbackUrl);

        new Thread() {
            @Override
            public void run() {
                int what = 1;

                try {
                    mHttpOauthprovider.retrieveAccessToken(mHttpOauthConsumer,
                            verifier);

                    mAccessToken = new AccessToken(
                            mHttpOauthConsumer.getToken(),
                            mHttpOauthConsumer.getTokenSecret());

                    configureToken();

                    User user = mTwitter.verifyCredentials();

                    mSession.storeAccessToken(mAccessToken, user.getName());

                    what = 0;
                } catch (Exception e) {
                    e.printStackTrace();
                }

                mHandler.sendMessage(mHandler.obtainMessage(what, 2, 0));
            }
        }.start();
    }

    private String getVerifier(String callbackUrl) {
        String verifier = "";

        try {
            callbackUrl = callbackUrl.replace("twitterapp", "http");

            URL url = new URL(callbackUrl);
            String query = url.getQuery();

            String array[] = query.split("&");

            for (String parameter : array) {
                String v[] = parameter.split("=");

                if (URLDecoder.decode(v[0]).equals(
                        oauth.signpost.OAuth.OAUTH_VERIFIER)) {
                    verifier = URLDecoder.decode(v[1]);
                    break;
                }
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }

        return verifier;
    }

    private void showLoginDialog(String url) {
        final TwDialogListener listener = new TwDialogListener() {

            public void onComplete(String value) {
                processToken(value);
            }

            public void onError(String value) {
                mListener.onError("Failed opening authorization page");
            }
        };

        new TwitterDialog(context, url, listener).show();
    }

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            mProgressDlg.dismiss();

            if (msg.what == 1) {
                if (msg.arg1 == 1)
                    mListener.onError("Error getting request token");
                else
                    mListener.onError("Error getting access token");
            } else {
                if (msg.arg1 == 1)
                    showLoginDialog((String) msg.obj);
                else
                    mListener.onComplete("");
            }
        }
    };

    public interface TwDialogListener {
        public void onComplete(String value);

        public void onError(String value);
    }
}


Class 2:- (TwitterDialog.java)

package com.twitter.android;

import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.Display;
import android.view.ViewGroup;
import android.view.Window;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.twitter.android.TwitterApp.TwDialogListener;

public class TwitterDialog extends Dialog {

    static final float[] DIMENSIONS_LANDSCAPE = { 460, 260 };
    static final float[] DIMENSIONS_PORTRAIT = { 280, 420 };
    static final FrameLayout.LayoutParams FILL = new FrameLayout.LayoutParams(
            ViewGroup.LayoutParams.FILL_PARENT,
            ViewGroup.LayoutParams.FILL_PARENT);
    static final int MARGIN = 4;
    static final int PADDING = 2;
    private String mUrl;
    private TwDialogListener mListener;
    private ProgressDialog mSpinner;
    private WebView mWebView;
    private LinearLayout mContent;
    private TextView mTitle;
    private boolean progressDialogRunning = false;

    public TwitterDialog(Context context, String url, TwDialogListener listener) {
        super(context);
        mUrl = url;
        mListener = listener;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mSpinner = new ProgressDialog(getContext());
        mSpinner.requestWindowFeature(Window.FEATURE_NO_TITLE);
        mSpinner.setMessage("Loading...");
        mContent = new LinearLayout(getContext());
        mContent.setOrientation(LinearLayout.VERTICAL);

        setUpTitle();
        setUpWebView();

        Display display = getWindow().getWindowManager().getDefaultDisplay();
        final float scale = getContext().getResources().getDisplayMetrics().density;
        float[] dimensions = (display.getWidth() < display.getHeight()) ? DIMENSIONS_PORTRAIT
                : DIMENSIONS_LANDSCAPE;
        addContentView(mContent, new FrameLayout.LayoutParams(
                (int) (dimensions[0] * scale + 0.5f), (int) (dimensions[1]
                        * scale + 0.5f)));
    }

    private void setUpTitle() {
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        Drawable icon = getContext().getResources().getDrawable(
                R.drawable.twitter_icon);
        mTitle = new TextView(getContext());
        mTitle.setText("Twitter");
        mTitle.setTextColor(Color.WHITE);
        mTitle.setTypeface(Typeface.DEFAULT_BOLD);
        mTitle.setBackgroundColor(0xFFbbd7e9);
        mTitle.setPadding(MARGIN + PADDING, MARGIN, MARGIN, MARGIN);
        mTitle.setCompoundDrawablePadding(MARGIN + PADDING);
        mTitle.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null);
        mContent.addView(mTitle);
    }

    private void setUpWebView() {
        mWebView = new WebView(getContext());
        mWebView.setVerticalScrollBarEnabled(false);
        mWebView.setHorizontalScrollBarEnabled(false);
        mWebView.setWebViewClient(new TwitterWebViewClient());
        mWebView.getSettings().setJavaScriptEnabled(true);
        mWebView.loadUrl(mUrl);
        mWebView.setLayoutParams(FILL);
        mContent.addView(mWebView);
    }

    private class TwitterWebViewClient extends WebViewClient {

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            if (url.startsWith(TwitterApp.CALLBACK_URL)) {
                mListener.onComplete(url);

                TwitterDialog.this.dismiss();

                return true;
            } else if (url.startsWith("authorize")) {
                return false;
            }
            return true;
        }

        @Override
        public void onReceivedError(WebView view, int errorCode,
                String description, String failingUrl) {
            super.onReceivedError(view, errorCode, description, failingUrl);
            mListener.onError(description);
            TwitterDialog.this.dismiss();
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
            mSpinner.show();
            progressDialogRunning = true;
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            String title = mWebView.getTitle();
            if (title != null && title.length() > 0) {
                mTitle.setText(title);
            }
            progressDialogRunning = false;
            mSpinner.dismiss();
        }
    }
   
    @Override
    protected void onStop() {
        progressDialogRunning = false;
        super.onStop();
    }

    public void onBackPressed() {
        if(!progressDialogRunning){
            TwitterDialog.this.dismiss();
        }
    }
}


Class 3:- (TwitterSession.java)

package com.twitter.android;

import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.Context;
import twitter4j.http.AccessToken;

public class TwitterSession {
    private SharedPreferences sharedPref;
    private Editor editor;

    private static final String TWEET_AUTH_KEY = "auth_key";
    private static final String TWEET_AUTH_SECRET_KEY = "auth_secret_key";
    private static final String TWEET_USER_NAME = "user_name";
    private static final String SHARED = "Twitter_Preferences";

    public TwitterSession(Context context) {
        sharedPref = context.getSharedPreferences(SHARED, Context.MODE_PRIVATE);
        editor = sharedPref.edit();
    }

    public void storeAccessToken(AccessToken accessToken, String username) {
        editor.putString(TWEET_AUTH_KEY, accessToken.getToken());
        editor.putString(TWEET_AUTH_SECRET_KEY, accessToken.getTokenSecret());
        editor.putString(TWEET_USER_NAME, username);
        editor.commit();
    }

    public void resetAccessToken() {
        editor.putString(TWEET_AUTH_KEY, null);
        editor.putString(TWEET_AUTH_SECRET_KEY, null);
        editor.putString(TWEET_USER_NAME, null);
        editor.commit();
    }

    public String getUsername() {
        return sharedPref.getString(TWEET_USER_NAME, "");
    }

    public AccessToken getAccessToken() {
        String token = sharedPref.getString(TWEET_AUTH_KEY, null);
        String tokenSecret = sharedPref.getString(TWEET_AUTH_SECRET_KEY, null);

        if (token != null && tokenSecret != null)
            return new AccessToken(token, tokenSecret);
        else
            return null;
    }
}

Add Following Jar File as a Refrence Library to Your Project

1)     signpost-commonshttp4-1.2.1.1.jar
2)     signpost-core-1.2.1.1.jar
3)     signpost-jetty6-1.2.1.1.jar
4)     twitter4j-core-2.1.6.jar


Now Run Your Project.

Enjoy :----)

You can download full source code from below link.

Android - Twitter

Don’t forget to provide feedback or follow this blog, if you find this blog is useful.

102 comments:

  1. Hello Dipak,

    Your Project is not working i copied all your java files as well as add jar files. java files are not giving any error but twitter is also not opening in dialog what you called.just post your main xml also so it will clear to me.

    ReplyDelete
    Replies
    1. Hello RajKumari,

      Here main.xml is not needed and Are you giving the permission of Internet into your manifest file?

      Delete
  2. Hi, I am getting error in this code like.. could not find the class TwitterFactory and so on... Could you please post the full code as a zip file..
    Thank u

    ReplyDelete
    Replies
    1. Hello Swathi,

      Please Add All Jar Files and give Reference of all jar files to your project.

      Delete
  3. Hi Dipak keshariya,

    I tried this code and added all the jar files but still i am getting the error. can you please fix the bug.
    Thank you.

    ReplyDelete
    Replies
    1. Hello Nama,

      Which Error Are you getting?

      Delete
  4. Do you don't have a scene or what?
    When your posting something, post it complete thing, Try to put your main.xml as well as Android Manifest file. Otherwise your post will be not be useful at all.

    Its all time waste for us, who 's following your incomplete post & also no proper reply for any question.

    ReplyDelete
    Replies
    1. Hello Krishna Kumar,

      The Post is only for reference to all and help to all, i am giving response asap and in above twitter integration example main.xml is not needed so i am not showing that file here and if you have any problem then tell me but don't give advice.

      Delete
  5. Please share all files so we can come to know better.. as i am new to development

    ReplyDelete
    Replies
    1. Give me your Email Address, I will send you Demo Application.

      Delete
    2. send me also at mahesh.subudhi@gmail.com

      Delete
    3. send me the demo application ..mshemanth11@gmail.com

      Delete
  6. please send me the proper code
    i really need it...
    i want to share the image on twitter account by clicking on some button...
    thanks in advance
    abhishek16dec@gmail.com

    ReplyDelete
    Replies
    1. Hello Abhishek,

      Please download full source code from above link.

      Delete
    2. where is the link to download...

      Delete
    3. https://www.dropbox.com/s/13fqi25oslx55qz/Twitter%20-%20Android.zip

      Delete
  7. Please email me a working project tired of searching in google is there any pblm bcz of Oauth changes..??

    ReplyDelete
    Replies
    1. Hello Reghunathan,

      Please download full source code from above link.

      Delete
  8. send working example to this mail id : ganesh.rrp@gmail.com

    ReplyDelete
    Replies
    1. Hello Ganesh,

      Please download full source code from above link.

      Delete
  9. hi,
    Please send your working sample or demo application at
    anujmukul@hotmail.com

    Would like to see if this works on not.

    Thanks.

    ReplyDelete
    Replies
    1. Hello Shraddha,

      Please download full source code from above link.

      Delete
  10. Can you send me a demo application?

    My email: sonbxhedspi@gmail.com

    Thanks :)

    ReplyDelete
    Replies
    1. Hello Kira,

      Please download full source code from above link.

      Delete
  11. Great tutorial ..its work fine ..
    only I did comment these lines then its works properly........
    }

    public void onClick(View v) {

    Thanks Deepak ....

    ReplyDelete
    Replies
    1. hi Vabhav
      please send me your working programe in a zip file to me
      its urgently needed
      govindachandra_p@yahoo.com

      Delete
  12. could u please send me the source code to these is id
    ramyavinoth02@gmail.com

    ReplyDelete
    Replies
    1. Please download full source code from above link.

      Delete
  13. Thank you for your codes. It's helpful to me. :)

    ReplyDelete
  14. Thank you for you code it is very help full for me . i am trying different api but not working your code is exactly work for me thank you very much for your great work.

    ReplyDelete
  15. Dipak Keshariya

    sir can you help me how to set my own msg in this demo app.
    it always posting same msg. instate i want to post my custom string.

    give your advice where to change code. i didnt get idea.

    thank you,
    keyur

    ReplyDelete
    Replies
    1. Hello Keyur,

      In TwitterApp.java file There is one string variable is defined, you can set your message in that variable.

      Delete
  16. it shows oAuthCommunication Error on 4.0 version android......any solution for this....

    ReplyDelete
    Replies
    1. Download Full source code from above link and try and after that if you have any issue then tell me.

      Delete
    2. application stopped unfortunately on start

      Delete
  17. Hi,I tried your sample code,and I got log in this code :Error getting request token.Could you help me? T hanks a lot.

    ReplyDelete
    Replies
    1. Hello,

      Please Download full source code from above link and after that if you have any problem then mail me on my mail id, so i will give you Complete solution with my Consumer_Key and Consumer_Secret_Key for testing purpose.

      Delete
    2. The tutorial is fantastic .. I am having trouble with using it though .. Once logged in ,it should not show authenticating dialog again ..It is showing in this case and when tried to repost the comment , it says login failed. When restarted the app,it worked. Do I have to do anything in onResume ?

      Delete
    3. Hello Akshay,

      This error is occurred because you are posting same status more than one time. the twitter4j library not allowed to post same status.

      Delete
    4. No thats not my concern .. The error should be duplicate post and not login failed which is coming if we try to post the comment more than once after the start of an Activity. My major concern is ,it displays dialog box each time even after I have logged into it once ... What can be done for this ?

      Delete
    5. Hello Akshay,

      Store Access Token in shared preferences on first time login and after check in your activity, if user is logged in then no need to login again and if user is not logged in then open twitter login dialog.

      Delete
    6. hey dipak ,

      It is showing logon failed after i click "authorise app" .what am i doing wrong here?

      Delete
  18. Please send me demo app. My id is vn.gupta86@gmail.com

    ReplyDelete
    Replies
    1. Hello Vinay,

      Download Complete Source code from above link.

      Delete
  19. Hello Deepak,
    your code is really good its working properly,thank you so much.

    ReplyDelete
  20. Hello Deepak,
    I have written the same code and also given reference of all the java files mentioned above and also given the permission to access the internet though twitter is not opening.
    Please help me out.
    And also i wanted to know about facebook itegration.
    Mail id :- nirmal.shah.29@gmail.com

    ReplyDelete
  21. I downloaded the project and I try to post message and image but it is posting only the message,how to solve this issue

    ReplyDelete
  22. your code is good its working properly,thank you.

    ReplyDelete
    Replies
    1. hi. could u pls send me demo project code. i really need it. my id is nidhigupta6761@gmail.
      com

      Delete
  23. working fine but what should i do for posting a edit text value

    ReplyDelete
  24. Hi Deepak , when i am trying to login to my twitter account it is giving me toast login failed, though i am providing correct username and password

    ReplyDelete
    Replies
    1. Implementing retrieveRequestToken and retrieveAccessToken via async task sorted this issue

      Reference https://code.google.com/p/montrealtransit-for-android/source/browse/trunk/MonTransit/src/org/montrealtransit/android/TwitterUtils.java?r=556

      Delete
    2. Implementing retrieveRequestToken and retrieveAccessToken via async task sorted this issue

      Reference https://code.google.com/p/montrealtransit-for-android/source/browse/trunk/MonTransit/src/org/montrealtransit/android/TwitterUtils.java?r=556

      Delete
    3. I am not getting how to do this could you please help

      Delete
  25. Same with me not working Im also getting the login failed even after multiple login attempts and even if my profile is displayed in authorize app(which means im logged in twitter) page it shows a login failed error when it returns to the app

    ReplyDelete
    Replies
    1. I ve posted by error logs below

      Delete
    2. Implementing retrieveRequestToken and retrieveAccessToken via async task sorted this issue

      Reference https://code.google.com/p/montrealtransit-for-android/source/browse/trunk/MonTransit/src/org/montrealtransit/android/TwitterUtils.java?r=556

      Delete
  26. My error Log

    04-05 21:38:16.038: W/webcore(24625): java.lang.Throwable: EventHub.removeMessages(int what = 107) is not supported before the WebViewCore is set up.
    04-05 21:38:16.038: W/webcore(24625): at android.webkit.WebViewCore$EventHub.removeMessages(WebViewCore.java:2404)
    04-05 21:38:16.038: W/webcore(24625): at android.webkit.WebViewCore$EventHub.access$12300(WebViewCore.java:1180)


    java.net.MalformedURLException: Unknown protocol: x-oauthflow-twitter
    at java.net.URL.(URL.java:184)
    at java.net.URL.(URL.java:127)

    com.twitter.android.TwitterApp.getVerifier(TwitterApp.java:186)
    com.twitter.android.TwitterApp.processToken(TwitterApp.java:149)
    at com.twitter.android.TwitterApp$4.onComplete(TwitterApp.java:211)
    at com.twitter.android.TwitterDialog$TwitterWebViewClient.shouldOverrideUrlLoading(TwitterDialog.java:109)
    oauth.signpost.exception.OAuthCommunicationException: Communication with the service provider failed: http://api.twitter.com/oauth/access_token
    oauth.signpost.AbstractOAuthProvider.retrieveToken(AbstractOAuthProvider.java:214)
    oauth.signpost.AbstractOAuthProvider.retrieveAccessToken(AbstractOAuthProvider.java:97)

    Caused by: java.io.FileNotFoundException: http://api.twitter.com/oauth/access_token
    libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:177)
    oauth.signpost.basic.HttpURLConnectionResponseAdapter.getContent(HttpURLConnectionResponseAdapter.java:18)
    oauth.signpost.AbstractOAuthProvider.handleUnexpectedResponse(AbstractOAuthProvider.java:228)
    oauth.signpost.AbstractOAuthProvider.retrieveToken(AbstractOAuthProvider.java:189)
    04-05 21:27:40.688: W/System.err(23964): ... 2 more
    04-05 21:27:40.703: E/TWITTER(23964): Error getting access token

    ReplyDelete
  27. Implementing retrieveRequestToken and retrieveAccessToken via async task sorted this issue

    Reference https://code.google.com/p/montrealtransit-for-android/source/browse/trunk/MonTransit/src/org/montrealtransit/android/TwitterUtils.java?r=556

    ReplyDelete
  28. Hello, I downloaded the code, make the project and it works only with your consumer key and secret. With mine doesn't work, do yoy know what can be the problem?

    ReplyDelete
  29. Hi,
    I downloaded the zip file .Created my own Consumer key & Consumer Secret .but while login this error is coming and login getting failed .
    Error msg : Error getting request token

    help me .its urgent

    ReplyDelete
  30. Thanks your sample.
    But when I run app,It shows message "Login fail",
    After I debug ,mAccessToken=null.

    Ofcouse I use my account with myConsumer key,Consumer secret and
    Application Type I check Read, Write and Access direct messages.

    And I try another accout. But result as the same old.I don't understand why.

    ReplyDelete
  31. I allaso downloaded the zip file .Created my own Consumer key & Consumer Secret .but while login this error is coming and login getting failed .
    Error msg : Error getting request token

    help me quickly .its very urgent!

    ReplyDelete
  32. i am also getting the same error can you please help me out...i was using it before one week ,it was working fine..then i don't know how or why it stopped can you please send me the working code.

    thanks in advance.

    showketahmad257@gmail.com

    I hope your help to come fast.

    ReplyDelete
  33. Login Failed Can you please let us know while this error come,after login to our twitter account

    ReplyDelete
  34. There is a small bug that causes login failed, but is pretty easy to solve:

    The error is MalFormedUrlException: Unknown protocol: x-oauthflow-twitter because in the method getVerifier (line 188 TwitterApp.java) we are trying to replace "twitterapp" text from the callBakUrl when we are using "x-oauthflow-twitter" text before the URL.

    We only need to change:
    callbackUrl = callbackUrl.replace("twitterapp", "http");
    TO
    callbackUrl = callbackUrl.replace("x-oauthflow-twitter", "http");


    Also, we can solve changing the original value of the variable OAUTH_CALLBACK_SCHEME.

    Another solution is always to replace all the text before ":":
    callbackUrl = "http"+ callbackUrl.substring(callbackUrl.indexOf(":"));

    By the way, thanks the author for the great code, there are too few examples working with twitter4j :)

    ReplyDelete
  35. I am getting login failed while giving my twitter credentials

    ReplyDelete
  36. Can you please help me..
    Its very urgent because i need to integrate my clinet app using ur code

    plz send upload exact code for me

    ReplyDelete
  37. Error msg : Error getting request token

    help me quickly .its very urgent!

    ReplyDelete
  38. For the people who are getting the Login Failed error, check this link, it helped me to solve the problem:

    http://stackoverflow.com/questions/6163111/twitter-api-not-accepting-callback-url-for-android-app

    ReplyDelete
  39. please Help me.
    I got This type error.

    {"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}]}


    Error getting Access Token.

    ReplyDelete
  40. Hi,

    If i use your CONSUMER_KEY + your CONSUMER_SECRET, it works but if I set mines, I have 401 error ! Is there a specific configuration in twitter application ?

    thx

    ReplyDelete
  41. hi ,
    i m tried ur project code but i got an error....like "get access token" plz help me...

    ReplyDelete
  42. 08-30 10:09:09.289: W/System.err(1262): java.net.MalformedURLException: Unknown protocol: x-oauthflow-twitter
    08-30 10:09:09.289: W/System.err(1262): at java.net.URL.(URL.java:184)
    08-30 10:09:09.299: W/System.err(1262): at java.net.URL.(URL.java:127)
    08-30 10:09:09.299: W/System.err(1262): at com.twitter.android.TwitterApp.getVerifier(TwitterApp.java:186)
    08-30 10:09:09.299: W/System.err(1262): at com.twitter.android.TwitterApp.processToken(TwitterApp.java:149)
    08-30 10:09:09.299: W/System.err(1262): at com.twitter.android.TwitterApp$4.onComplete(TwitterApp.java:211)
    08-30 10:09:09.299: W/System.err(1262): at com.twitter.android.TwitterDialog$TwitterWebViewClient.shouldOverrideUrlLoading(TwitterDialog.java:109)
    08-30 10:09:09.309: W/System.err(1262): at android.webkit.CallbackProxy.uiOverrideUrlLoading(CallbackProxy.java:270)
    08-30 10:09:09.309: W/System.err(1262): at android.webkit.CallbackProxy.handleMessage(CallbackProxy.java:372)
    08-30 10:09:09.309: W/System.err(1262): at android.os.Handler.dispatchMessage(Handler.java:99)
    08-30 10:09:09.309: W/System.err(1262): at android.os.Looper.loop(Looper.java:137)
    08-30 10:09:09.309: W/System.err(1262): at android.app.ActivityThread.main(ActivityThread.java:5041)
    08-30 10:09:09.309: W/System.err(1262): at java.lang.reflect.Method.invokeNative(Native Method)
    08-30 10:09:09.309: W/System.err(1262): at java.lang.reflect.Method.invoke(Method.java:511)
    08-30 10:09:09.309: W/System.err(1262): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
    08-30 10:09:09.309: W/System.err(1262): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
    08-30 10:09:09.319: W/System.err(1262): at dalvik.system.NativeStart.main(Native Method)
    08-30 10:09:09.589: I/Choreographer(1262): Skipped 62 frames! The application may be doing too much work on its main thread.
    08-30 10:09:09.889: I/Choreographer(1262): Skipped 70 frames! The application may be doing too much work on its main thread.
    08-30 10:09:10.599: I/Choreographer(1262): Skipped 34 frames! The application may be doing too much work on its main thread.
    08-30 10:09:11.049: W/System.err(1262): oauth.signpost.exception.OAuthCommunicationException: Communication with the service provider failed: http://api.twitter.com/oauth/access_token
    08-30 10:09:11.109: W/System.err(1262): at oauth.signpost.AbstractOAuthProvider.retrieveToken(AbstractOAuthProvider.java:214)
    08-30 10:09:11.109: W/System.err(1262): at oauth.signpost.AbstractOAuthProvider.retrieveAccessToken(AbstractOAuthProvider.java:97)
    08-30 10:09:11.139: W/System.err(1262): at com.twitter.android.TwitterApp$3.run(TwitterApp.java:157)
    08-30 10:09:11.139: W/System.err(1262): Caused by: java.io.FileNotFoundException: http://api.twitter.com/oauth/access_token
    08-30 10:09:11.179: W/System.err(1262): at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:186)
    08-30 10:09:11.179: W/System.err(1262): at oauth.signpost.basic.HttpURLConnectionResponseAdapter.getContent(HttpURLConnectionResponseAdapter.java:18)
    08-30 10:09:11.179: W/System.err(1262): at oauth.signpost.AbstractOAuthProvider.handleUnexpectedResponse(AbstractOAuthProvider.java:228)
    08-30 10:09:11.189: W/System.err(1262): at oauth.signpost.AbstractOAuthProvider.retrieveToken(AbstractOAuthProvider.java:189)
    08-30 10:09:11.189: W/System.err(1262): ... 2 more
    08-30 10:09:11.349: E/TWITTER(1262): Error getting access token
    08-30 10:09:11.349: I/Choreographer(1262): Skipped 31 frames! The application may be doing too much work on its main thread.
    login faild..

    ReplyDelete
  43. Sorry Dipak but this is not working.
    i have tried many times but each time found login failed.

    ReplyDelete
  44. Hai i got a login failed error please help me thanks...

    ReplyDelete
  45. There was error in the code for below lines-
    StrictMath.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
    .permitAll().build();
    StrictMode.setThreadPolicy(policy);
    after commenting them i'm getting following exception.code is not working.
    10-14 14:31:15.637: E/AndroidRuntime(1201): FATAL EXCEPTION: main
    10-14 14:31:15.637: E/AndroidRuntime(1201): java.lang.VerifyError: com.twitter.android.TwitterApp
    10-14 14:31:15.637: E/AndroidRuntime(1201): at com.android.twitter.TwitterActivity.onCreate(TwitterActivity.java:36)
    10-14 14:31:15.637: E/AndroidRuntime(1201): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
    10-14 14:31:15.637: E/AndroidRuntime(1201): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
    10-14 14:31:15.637: E/AndroidRuntime(1201): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
    10-14 14:31:15.637: E/AndroidRuntime(1201): at android.app.ActivityThread.access$2300(ActivityThread.java:125)
    10-14 14:31:15.637: E/AndroidRuntime(1201): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
    10-14 14:31:15.637: E/AndroidRuntime(1201): at android.os.Handler.dispatchMessage(Handler.java:99)
    10-14 14:31:15.637: E/AndroidRuntime(1201): at android.os.Looper.loop(Looper.java:123)
    10-14 14:31:15.637: E/AndroidRuntime(1201): at android.app.ActivityThread.main(ActivityThread.java:4627)
    10-14 14:31:15.637: E/AndroidRuntime(1201): at java.lang.reflect.Method.invokeNative(Native Method)
    10-14 14:31:15.637: E/AndroidRuntime(1201): at java.lang.reflect.Method.invoke(Method.java:521)
    10-14 14:31:15.637: E/AndroidRuntime(1201): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
    10-14 14:31:15.637: E/AndroidRuntime(1201): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
    10-14 14:31:15.637: E/AndroidRuntime(1201): at dalvik.system.NativeStart.main(Native Method)

    ReplyDelete
  46. i am run on a emulator login success but run on a device is login fail

    ReplyDelete
  47. your project is working but by that i am not able to login ...it is displaying only login failed .......


    .....plzzz help me out ..............

    ReplyDelete
  48. {"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}]}

    ReplyDelete
  49. Hi Deepak,
    I am stuck in a project, hope you could help me. I want to show all the twitter tweets in my android list view from a twitter public page(e.g www.twitter.com/givecentral). I have written all the code and also created consumer key and secret key. But the application is getting stopped everytime. Can you help me on this and send me the working source code. My id is mukesh17m@gmail.com.. Hope you'll reply me soon..

    ReplyDelete
  50. When i run program, by anyway, resulf is Login Fail. It caused by Communication with the service provider failed : http://api.twitter.com/oauth/access_token. Please help me

    ReplyDelete
    Replies
    1. have you registered your application with https://dev.twitter.com ? Please register your application here and generate Access Token and Access TOken Secret key + replace the consumer key and secret key of the above code with your application's keys and try. i changed the application access from read only to read/write also so it will be able to post tweets on my account, still i'm facing issue getting the login page but i'm able to see my application's icon on the webview.

      Delete
  51. This comment has been removed by the author.

    ReplyDelete
  52. i found out that you have not described about mentioning the entry of callback url in android meinfiest file :





    As per your appliaction's code , line must be added .
    please let me know what callback url you have used while registering your application in twitter dev

    ReplyDelete
    Replies
    1. add - data android:scheme="x-oauthflow-twitter" android:host="callback"/
      inside Intent filter in android meinfiest file

      Delete
  53. Hello Sir,
    I am getting Login Failed toast each time..
    Exception is OauthCommunicationexception

    ReplyDelete
  54. Hello Deepak,I Implement ur code,,but I got error getting access token..i can i solve it??

    ReplyDelete
  55. Hi, i downloaded your zip file, extracted and imported in to my eclipse workspace. I replaced TWEET_AUTH_KEY, TWEET_AUTH_SECRET_KEY in the TwitterSession.java and run the application, "Login Failed" toast is displaying every time i login. This is logcat http://www.evernote.com/shard/s283/sh/ccf921a3-79fd-4eb2-82ae-7c818c0e24ac/bef5d02ee96fc47921038f518abec021 please help me sloving the problem OR mail me the latest zip file (shashishiva9@gmail.com)

    ReplyDelete
  56. Hello,I Implement ur code,,but I got error getting access token..i can i solve it??...every time i login it shows the "Login Failed" toast is displaying ...plese help me...

    04-03 10:39:34.326: W/System.err(864): java.net.MalformedURLException: Unknown protocol: x-oauthflow-twitter
    04-03 10:39:34.475: W/System.err(864): at java.net.URL.(URL.java:184)
    04-03 10:39:34.505: W/System.err(864): at java.net.URL.(URL.java:127)
    04-03 10:39:34.625: W/System.err(864): at com.twitter.android.TwitterApp.getVerifier(TwitterApp.java:203)
    04-03 10:39:34.625: W/System.err(864): at com.twitter.android.TwitterApp.processToken(TwitterApp.java:163)
    04-03 10:39:34.636: W/System.err(864): at com.twitter.android.TwitterApp$4.onComplete(TwitterApp.java:233)
    04-03 10:39:34.645: W/System.err(864): at com.twitter.android.TwitterDialog$TwitterWebViewClient.shouldOverrideUrlLoading(TwitterDialog.java:109)
    04-03 10:39:34.665: W/System.err(864): at android.webkit.CallbackProxy.uiOverrideUrlLoading(CallbackProxy.java:224)
    04-03 10:39:34.665: W/System.err(864): at android.webkit.CallbackProxy.handleMessage(CallbackProxy.java:324)
    04-03 10:39:34.665: W/System.err(864): at android.os.Handler.dispatchMessage(Handler.java:99)
    04-03 10:39:34.665: W/System.err(864): at android.os.Looper.loop(Looper.java:137)
    04-03 10:39:34.665: W/System.err(864): at android.app.ActivityThread.main(ActivityThread.java:4340)
    04-03 10:39:34.665: W/System.err(864): at java.lang.reflect.Method.invokeNative(Native Method)
    04-03 10:39:34.675: W/System.err(864): at java.lang.reflect.Method.invoke(Method.java:511)
    04-03 10:39:34.675: W/System.err(864): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
    04-03 10:39:34.685: W/System.err(864): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
    04-03 10:39:34.685: W/System.err(864): at dalvik.system.NativeStart.main(Native Method)
    04-03 10:39:36.075: W/System.err(864): oauth.signpost.exception.OAuthCommunicationException: Communication with the service provider failed: http://api.twitter.com/oauth/access_token
    04-03 10:39:36.075: W/System.err(864): at oauth.signpost.AbstractOAuthProvider.retrieveToken(AbstractOAuthProvider.java:214)
    04-03 10:39:36.138: W/System.err(864): at oauth.signpost.AbstractOAuthProvider.retrieveAccessToken(AbstractOAuthProvider.java:97)
    04-03 10:39:36.138: W/System.err(864): at com.twitter.android.TwitterApp$3.run(TwitterApp.java:174)
    04-03 10:39:36.185: W/System.err(864): Caused by: java.io.FileNotFoundException: http://api.twitter.com/oauth/access_token
    04-03 10:39:36.215: W/System.err(864): at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:177)
    04-03 10:39:36.255: W/System.err(864): at oauth.signpost.basic.HttpURLConnectionResponseAdapter.getContent(HttpURLConnectionResponseAdapter.java:18)
    04-03 10:39:36.255: W/System.err(864): at oauth.signpost.AbstractOAuthProvider.handleUnexpectedResponse(AbstractOAuthProvider.java:228)
    04-03 10:39:36.275: W/System.err(864): at oauth.signpost.AbstractOAuthProvider.retrieveToken(AbstractOAuthProvider.java:189)
    04-03 10:39:36.275: W/System.err(864): ... 2 more
    04-03 10:39:36.567: E/TWITTER(864): Error getting access token

    ReplyDelete
  57. Getting login fail toast.how to resolve?

    ReplyDelete
  58. Hello Dipak,

    How to post the image on twitter
    i am using below code

    public void updateStatus(String status) throws Exception {
    try {
    StatusUpdate su=new StatusUpdate("Vishal");
    File sdCardRoot = Environment.getExternalStorageDirectory();
    File yourDir = new File(sdCardRoot, "/DCIM/Camera/Vishal.jpg");
    if(yourDir.exists())
    su.setMedia(yourDir);
    else
    System.out.println("File not present");
    mTwitter.updateStatus(status);
    // File f = new File("/mnt/sdcard/74.jpg");
    // mTwitter.updateProfileImage(f);
    } catch (TwitterException e) {
    throw e;
    }
    }

    ReplyDelete
  59. After pressing twitter button I am getting a twitter login screen..after providing username and password..it generates a toast "login failed" can you please help..thanks

    ReplyDelete
  60. 04-11 12:19:34.667: W/System.err(767): java.net.MalformedURLException: Unknown protocol: oauth
    04-11 12:19:34.677: W/System.err(767): at java.net.URL.(URL.java:184)
    04-11 12:19:34.677: W/System.err(767): at java.net.URL.(URL.java:127)
    04-11 12:19:34.677: W/System.err(767): at com.twitter.android.TwitterApp.getVerifier(TwitterApp.java:185)
    04-11 12:19:34.677: W/System.err(767): at com.twitter.android.TwitterApp.processToken(TwitterApp.java:147)
    04-11 12:19:34.677: W/System.err(767): at com.twitter.android.TwitterApp$4.onComplete(TwitterApp.java:210)
    04-11 12:19:34.677: W/System.err(767): at com.twitter.android.TwitterDialog$TwitterWebViewClient.shouldOverrideUrlLoading(TwitterDialog.java:112)
    04-11 12:19:34.677: W/System.err(767): at android.webkit.CallbackProxy.uiOverrideUrlLoading(CallbackProxy.java:261)
    04-11 12:19:34.687: W/System.err(767): at android.webkit.CallbackProxy.handleMessage(CallbackProxy.java:363)
    04-11 12:19:34.687: W/System.err(767): at android.os.Handler.dispatchMessage(Handler.java:99)
    04-11 12:19:34.687: W/System.err(767): at android.os.Looper.loop(Looper.java:137)
    04-11 12:19:34.687: W/System.err(767): at android.app.ActivityThread.main(ActivityThread.java:5103)
    04-11 12:19:34.687: W/System.err(767): at java.lang.reflect.Method.invokeNative(Native Method)
    04-11 12:19:34.687: W/System.err(767): at java.lang.reflect.Method.invoke(Method.java:525)
    04-11 12:19:34.697: W/System.err(767): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
    04-11 12:19:34.697: W/System.err(767): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
    04-11 12:19:34.697: W/System.err(767): at dalvik.system.NativeStart.main(Native Method)
    04-11 12:19:34.727: I/Choreographer(767): Skipped 65 frames! The application may be doing too much work on its main thread.
    04-11 12:19:35.077: I/Choreographer(767): Skipped 113 frames! The application may be doing too much work on its main thread.
    04-11 12:19:35.267: I/Choreographer(767): Skipped 81 frames! The application may be doing too much work on its main thread.
    04-11 12:19:35.667: W/System.err(767): oauth.signpost.exception.OAuthCommunicationException: Communication with the service provider failed: http://api.twitter.com/oauth/access_token
    04-11 12:19:35.667: W/System.err(767): at oauth.signpost.AbstractOAuthProvider.retrieveToken(AbstractOAuthProvider.java:214)
    04-11 12:19:35.697: W/System.err(767): at oauth.signpost.AbstractOAuthProvider.retrieveAccessToken(AbstractOAuthProvider.java:97)
    04-11 12:19:35.697: W/System.err(767): at com.twitter.android.TwitterApp$3.run(TwitterApp.java:155)
    04-11 12:19:35.697: W/System.err(767): Caused by: java.io.FileNotFoundException: http://api.twitter.com/oauth/access_token
    04-11 12:19:35.747: W/System.err(767): at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:186)
    04-11 12:19:35.747: W/System.err(767): at oauth.signpost.basic.HttpURLConnectionResponseAdapter.getContent(HttpURLConnectionResponseAdapter.java:18)
    04-11 12:19:35.797: W/System.err(767): at oauth.signpost.AbstractOAuthProvider.handleUnexpectedResponse(AbstractOAuthProvider.java:228)
    04-11 12:19:35.797: W/System.err(767): at oauth.signpost.AbstractOAuthProvider.retrieveToken(AbstractOAuthProvider.java:189)
    04-11 12:19:35.807: W/System.err(767): ... 2 more
    04-11 12:19:35.827: I/Choreographer(767): Skipped 32 frames! The application may be doing too much work on its main thread.
    04-11 12:19:35.877: E/TWITTER(767): Error getting access token

    ReplyDelete
  61. I am trying to run the sample given on https://www.dropbox.com/s/13fqi25oslx55qz/Twitter%20-%20Android.zip but getting toast Login Fail ?
    How to resolve this ?

    ReplyDelete
  62. Hi I have downlaod your demo code but i am getting Login failed message,Now what i do ......please reply......thank
    if you have working code plese share with me,
    my email Id is viswakarmalovekush@gmail.com

    ReplyDelete
  63. This comment has been removed by the author.

    ReplyDelete
  64. Thank you for providing approximately well running code but I got small error exception after login success and have also don't got access token ID.
    The error shown like this after login...
    1). oauth.signpost.exception.OAuthCommunicationException: Communication with the service provider failed: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

    2).oauth.signpost.AbstractOAuthProvider.retrieveToken(AbstractOAuthProvider.java:214)

    3). com.twitter.android.TwitterApp$2.run(TwitterApp.java:133)

    4). Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

    Have you solution of this problem.
    Used Lib:
    1). signpost-commonshttp4-1.2.1.1.jar
    2). signpost-core-1.2.1.1.jar
    3). signpost-jetty6-1.2.1.1.jar
    4). twitter4j-core-2.2.5.jar
    According to me below data are going through SSL and current libs are not support SSL certificate.
    private static final String TWITTER_ACCESS_TOKEN_URL = "https://api.twitter.com/oauth/access_token";
    private static final String TWITTER_AUTHORZE_URL = "https://api.twitter.com/oauth/authorize";
    private static final String TWITTER_REQUEST_URL = "https://api.twitter.com/oauth/request_token";

    Can you resolve it. I will always appreciated for this kind of help

    ReplyDelete