Android使用jtwitter抛出错误

我正在尝试在Android目标2.2上编写一个Twitter应用程序(使用我在网上找到的一些示例代码并使用Marko Gargenta的O’Reilly文本)。 我在下面的日志中遇到了问题。 首先给出源代码,然后是日志。 知道这里出了什么问题吗? 也有人有或可以指向在Android上运行的示例jtwitter代码。

谢谢,拉维


protected String doInBackground(String... statuses) { try { //Autho information /*OAuthSignpostClient oauthclient = new OAuthSignpostClient(cons_key, cons_secret, access_token, access_secret);*/ OAuthSignpostClient oauthclient = new OAuthSignpostClient(access_token, access_secret,"oob"); //***POSTING TO TWITTER CURRENTLY DOES NOT WORK WITH THIS INTERFACE twitter = new Twitter(mytwitterusername, oauthclient); //twitter.setAPIRootUrl("http://learningandroid.status.net/api"); //***POSTING TO TWITTER CURRENTLY DOES NOT WORK WITH THIS INTERFACE Log.i(Logtag, "Status currently is " + statuses[0]); Twitter.Status status = twitter.updateStatus(statuses[0]); //return status.text; return statuses[0]; } catch (TwitterException e) { Log.e(Logtag, e.toString()); e.printStackTrace(); return "Failed to post to Twitter"; } 

}


日志文件:

 E/dalvikvm( 719): Could not find method javax.swing.JOptionPane.showInputDialog, referenced from method winterwell.jtwi tter.OAuthSignpostClient.askUser W/dalvikvm( 719): VFY: unable to resolve static method 443: Ljavax/swing/JOptionPane;.showInputDialog (Ljava/lang/Objec t;)Ljava/lang/String; W/dalvikvm( 719): VFY: rejecting opcode 0x71 at 0x0000 W/dalvikvm( 719): VFY: rejected Lwinterwell/jtwitter/OAuthSignpostClient;.askUser (Ljava/lang/String;)Ljava/lang/Strin g; W/dalvikvm( 719): Verifier rejected class Lwinterwell/jtwitter/OAuthSignpostClient; W/dalvikvm( 719): threadid=17: thread exiting with uncaught exception (group=0x4000fe70) E/AndroidRuntime( 719): Uncaught handler: thread AsyncTask #1 exiting due to uncaught exception E/AndroidRuntime( 719): java.lang.RuntimeException: An error occured while executing doInBackground() E/AndroidRuntime( 719): at android.os.AsyncTask$3.done(AsyncTask.java:200) E/AndroidRuntime( 719): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:234) E/AndroidRuntime( 719): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:258) E/AndroidRuntime( 719): at java.util.concurrent.FutureTask.run(FutureTask.java:122) E/AndroidRuntime( 719): at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:648) E/AndroidRuntime( 719): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:673) E/AndroidRuntime( 719): at java.lang.Thread.run(Thread.java:1058) E/AndroidRuntime( 719): Caused by: java.lang.VerifyError: winterwell.jtwitter.OAuthSignpostClient E/AndroidRuntime( 719): at com.ravi.tweeto.StatusActivity$PostToTwitter.doInBackground(StatusActivity.java:81) E/AndroidRuntime( 719): at com.ravi.tweeto.StatusActivity$PostToTwitter.doInBackground(StatusActivity.java:1) E/AndroidRuntime( 719): at android.os.AsyncTask$2.call(AsyncTask.java:185) E/AndroidRuntime( 719): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:256) E/AndroidRuntime( 719): ... 4 more I/Process ( 585): Sending signal. PID: 719 SIG: 3 I/dalvikvm( 719): threadid=7: reacting to signal 3 I/dalvikvm( 719): Wrote stack trace to '/data/anr/traces.txt' ---- 

基本上,JTwitter库调用了不在Android SDK中的Java swing类,因为它不使用swing。 我必须得到JTwitter的源代码并删除我的应用程序的swing代码才能工作。 希望这可以帮助。

可能值得使用Twitter4J库作为替代方案。 我在Android应用程序中使用它没有任何问题。

我发现我在GitHub上使用的大部分代码(现在找不到确切的链接)对代码片段的一些搜索发送给我,但我不认为这是我从中得到它的确切网站。

但这就是我在半工作代码中所拥有的。

OAUTH.java


 import junit.framework.Assert; import oauth.signpost.OAuth; import oauth.signpost.OAuthConsumer; import oauth.signpost.OAuthProvider; import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer; import oauth.signpost.commonshttp.CommonsHttpOAuthProvider; import oauth.signpost.exception.OAuthCommunicationException; import oauth.signpost.exception.OAuthExpectationFailedException; import oauth.signpost.exception.OAuthMessageSignerException; import oauth.signpost.exception.OAuthNotAuthorizedException; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.net.Uri; import android.os.Bundle; import android.util.Log; public class OAUTH extends Activity { private static final String TAG = "OAUTH"; public static final String USER_TOKEN = "user_token"; public static final String USER_SECRET = "user_secret"; public static final String REQUEST_TOKEN = "request_token"; public static final String REQUEST_SECRET = "request_secret"; public static final String TWITTER_REQUEST_TOKEN_URL = "http://twitter.com/oauth/request_token"; public static final String TWITTER_ACCESS_TOKEN_URL = "http://twitter.com/oauth/access_token"; public static final String TWITTER_AUTHORIZE_URL = "http://twitter.com/oauth/authorize"; private static final Uri CALLBACK_URI = Uri.parse("gpsagenda://twitt"); public static final String PREFS = "MyPrefsFile"; private OAuthConsumer mConsumer = null; private OAuthProvider mProvider = null; SharedPreferences mSettings; public void onCreate(Bundle icicle) { super.onCreate(icicle); // We don't need to worry about any saved states: we can reconstruct the state mConsumer = new CommonsHttpOAuthConsumer( "myKey", "mySecret"); mProvider = new CommonsHttpOAuthProvider ( TWITTER_REQUEST_TOKEN_URL, TWITTER_ACCESS_TOKEN_URL, TWITTER_AUTHORIZE_URL); // It turns out this was the missing thing to making standard Activity launch mode work mProvider.setOAuth10a(true); mSettings = this.getSharedPreferences(PREFS, Context.MODE_PRIVATE); Intent i = this.getIntent(); if (i.getData() == null) { try { // This is really important. If you were able to register your real callback Uri with Twitter, and not some fake Uri // like I registered when I wrote this example, you need to send null as the callback Uri in this function call. Then // Twitter will correctly process your callback redirection String authUrl = mProvider.retrieveRequestToken(mConsumer, CALLBACK_URI.toString()); saveRequestInformation(mSettings, mConsumer.getToken(), mConsumer.getTokenSecret()); this.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(authUrl))); } catch (OAuthMessageSignerException e) { e.printStackTrace(); } catch (OAuthNotAuthorizedException e) { e.printStackTrace(); } catch (OAuthExpectationFailedException e) { e.printStackTrace(); } catch (OAuthCommunicationException e) { e.printStackTrace(); } } } @Override protected void onResume() { super.onResume(); Uri uri = getIntent().getData(); if (uri != null && CALLBACK_URI.getScheme().equals(uri.getScheme())) { String token = mSettings.getString(OAUTH.REQUEST_TOKEN, null); String secret = mSettings.getString(OAUTH.REQUEST_SECRET, null); Intent i = new Intent(this, DetailsContainer.class); // Currently, how we get back to main activity. try { if(!(token == null || secret == null)) { mConsumer.setTokenWithSecret(token, secret); } String otoken = uri.getQueryParameter(OAuth.OAUTH_TOKEN); String verifier = uri.getQueryParameter(OAuth.OAUTH_VERIFIER); // We send out and save the request token, but the secret is not the same as the verifier // Apparently, the verifier is decoded to get the secret, which is then compared - crafty // This is a sanity check which should never fail - hence the assertion Assert.assertEquals(otoken, mConsumer.getToken()); // This is the moment of truth - we could throw here mProvider.retrieveAccessToken(mConsumer, verifier); // Now we can retrieve the goodies token = mConsumer.getToken(); secret = mConsumer.getTokenSecret(); OAUTH.saveAuthInformation(mSettings, token, secret); // Clear the request stuff, now that we have the real thing OAUTH.saveRequestInformation(mSettings, null, null); i.putExtra(USER_TOKEN, token); i.putExtra(USER_SECRET, secret); } catch (OAuthMessageSignerException e) { e.printStackTrace(); } catch (OAuthNotAuthorizedException e) { e.printStackTrace(); } catch (OAuthExpectationFailedException e) { e.printStackTrace(); } catch (OAuthCommunicationException e) { e.printStackTrace(); } finally { startActivity(i); // we either authenticated and have the extras or not, but we're going back finish(); } } } public static void saveRequestInformation(SharedPreferences settings, String token, String secret) { // null means to clear the old values SharedPreferences.Editor editor = settings.edit(); if(token == null) { editor.remove(OAUTH.REQUEST_TOKEN); Log.d(TAG, "Clearing Request Token"); } else { editor.putString(OAUTH.REQUEST_TOKEN, token); Log.d(TAG, "Saving Request Token: " + token); } if (secret == null) { editor.remove(OAUTH.REQUEST_SECRET); Log.d(TAG, "Clearing Request Secret"); } else { editor.putString(OAUTH.REQUEST_SECRET, secret); Log.d(TAG, "Saving Request Secret: " + secret); } editor.commit(); } public static void saveAuthInformation(SharedPreferences settings, String token, String secret) { // null means to clear the old values SharedPreferences.Editor editor = settings.edit(); if(token == null) { editor.remove(OAUTH.USER_TOKEN); Log.d(TAG, "Clearing OAuth Token"); } else { editor.putString(OAUTH.USER_TOKEN, token); Log.d(TAG, "Saving OAuth Token: " + token); } if (secret == null) { editor.remove(OAUTH.USER_SECRET); Log.d(TAG, "Clearing OAuth Secret"); } else { editor.putString(OAUTH.USER_SECRET, secret); Log.d(TAG, "Saving OAuth Secret: " + secret); } editor.commit(); } } 

DetailsTwitter.java(我的“实现”)


 import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.LinkedList; import oauth.signpost.OAuthConsumer; import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer; import oauth.signpost.exception.OAuthCommunicationException; import oauth.signpost.exception.OAuthExpectationFailedException; import oauth.signpost.exception.OAuthMessageSignerException; import org.apache.http.HttpVersion; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.scheme.PlainSocketFactory; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.impl.client.BasicResponseHandler; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; import org.apache.http.message.BasicNameValuePair; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.apache.http.params.HttpProtocolParams; import org.apache.http.protocol.HTTP; import org.gpsagenda.OAUTH; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.app.Activity; import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; public class DetailsTwitter extends Activity { public SharedPreferences mSettings; private LinkedList mHomeStatus = new LinkedList(); public String mToken; public String mSecret; private OAuthConsumer mConsumer = null; private HttpClient mClient; private EditText mEditor; private TextView mLast; private CheckBox mCB; private Button mButton; private TextView mUser; private int ID; public static final String VERIFY_URL_STRING = "http://twitter.com/account/verify_credentials.json"; public static final String PUBLIC_TIMELINE_URL_STRING = "http://twitter.com/statuses/public_timeline.json"; public static final String USER_TIMELINE_URL_STRING = "http://twitter.com/statuses/user_timeline.json"; public static final String HOME_TIMELINE_URL_STRING = "http://api.twitter.com/1/statuses/home_timeline.json"; public static final String FRIENDS_TIMELINE_URL_STRING = "http://api.twitter.com/1/statuses/friends_timeline.json"; public static final String STATUSES_URL_STRING = "http://twitter.com/statuses/update.json"; ProgressDialog postDialog = null; public static final String TWITTER_REQUEST_TOKEN_URL = "http://twitter.com/oauth/request_token"; public static final String TWITTER_ACCESS_TOKEN_URL = "http://twitter.com/oauth/access_token"; public static final String TWITTER_AUTHORIZE_URL = "http://twitter.com/oauth/authorize"; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.detailstwittertab); HttpParams parameters = new BasicHttpParams(); HttpProtocolParams.setVersion(parameters, HttpVersion.HTTP_1_1); HttpProtocolParams.setContentCharset(parameters, HTTP.DEFAULT_CONTENT_CHARSET); HttpProtocolParams.setUseExpectContinue(parameters, false); HttpConnectionParams.setTcpNoDelay(parameters, true); HttpConnectionParams.setSocketBufferSize(parameters, 8192); SchemeRegistry schReg = new SchemeRegistry(); schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); ClientConnectionManager tsccm = new ThreadSafeClientConnManager(parameters, schReg); mClient = new DefaultHttpClient(tsccm, parameters); mCB = (CheckBox) this.findViewById(R.id.enable); mCB.setChecked(false); mEditor = (EditText) this.findViewById(R.id.editor); mButton = (Button) this.findViewById(R.id.post); mUser = (TextView) this.findViewById(R.id.user); mLast = (TextView) this.findViewById(R.id.last); mSettings = getSharedPreferences(OAUTH.PREFS, Context.MODE_PRIVATE); mConsumer = new CommonsHttpOAuthConsumer( "myKey", "mySecret"); } public void PostTweet(View v) { String postString = mEditor.getText().toString(); if (postString.length() == 0) { Toast.makeText(this, getText(R.string.tweet_empty), Toast.LENGTH_SHORT).show(); } else { BitlyAndroid bitly = new BitlyAndroid("iarwain01", "R_1bffd0176aa731a27e5b2d23cf043199"); String shortUrl = ""; // Try to get the corresponding ID of the POI try { ID = getIntent().getExtras().getInt("id"); } catch (NullPointerException e) { e.printStackTrace(); } try { shortUrl = bitly.getShortUrl("http://gpsagenda.ikdoeict.be/projecten2/index.php?module=places&id=" + ID); } catch (Exception e) { Log.e("Debug", "Link shortening failed!"); e.printStackTrace(); } new PostTask().execute(postString + " " + shortUrl); } } protected void onFinish() { mClient.getConnectionManager().shutdown(); } public void ConnectWithTwitter(View v) { if(mCB.isChecked()) { Intent i = new Intent(this, OAUTH.class); startActivity(i); } else { OAUTH.saveAuthInformation(mSettings, null, null); mButton.setEnabled(false); mEditor.setEnabled(false); mCB.setChecked(false); mUser.setText(""); } mCB.setChecked(false); // the oauth callback will set it to the proper state } @Override public void onResume() { super.onResume(); // We look for saved user keys if(mSettings.contains(OAUTH.USER_TOKEN) && mSettings.contains(OAUTH.USER_SECRET)) { mToken = mSettings.getString(OAUTH.USER_TOKEN, null); mSecret = mSettings.getString(OAUTH.USER_SECRET, null); if(!(mToken == null || mSecret == null)) { mConsumer.setTokenWithSecret(mToken, mSecret); } } new GetCredentialsTask().execute(); } // These parameters are needed to talk to the messaging service public HttpParams getParams() { // Tweak further as needed for your app HttpParams params = new BasicHttpParams(); // set this to false, or else you'll get an Expectation Failed: error HttpProtocolParams.setUseExpectContinue(params, false); return params; } //---------------------------- // This task posts a message to your message queue on the service. private class PostTask extends AsyncTask { ProgressDialog postDialog; @Override protected void onPreExecute() { postDialog = ProgressDialog.show(DetailsTwitter.this, getText(R.string.tweet_progress_title), getText(R.string.tweet_progress_text), true, // indeterminate duration false); // not cancel-able } @Override protected JSONObject doInBackground(String... params) { JSONObject jso = null; try { HttpPost post = new HttpPost("http://twitter.com/statuses/update.json"); LinkedList out = new LinkedList(); out.add(new BasicNameValuePair("status", params[0])); post.setEntity(new UrlEncodedFormEntity(out, HTTP.UTF_8)); post.setParams(getParams()); // sign the request to authenticate mConsumer.sign(post); String response = mClient.execute(post, new BasicResponseHandler()); jso = new JSONObject(response); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (OAuthMessageSignerException e) { e.printStackTrace(); } catch (OAuthExpectationFailedException e) { e.printStackTrace(); } catch (OAuthCommunicationException e) { e.printStackTrace(); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } finally { } return jso; } // This is in the UI thread, so we can mess with the UI protected void onPostExecute(JSONObject jso) { postDialog.dismiss(); if(jso != null) { // authorization succeeded, the json object contains the user information mEditor.setText(""); mLast.setText(getCurrentTweet(jso)); } else { mLast.setText(getText(R.string.tweet_error)); } } } // Get stuff from the two types of Twitter JSONObject we deal with: credentials and status private String getCurrentTweet(JSONObject status) { return status.optString("text", getString(R.string.bad_value)); } //---------------------------- // This task is run on every onResume(), to make sure the current credentials are valid. // This is probably overkill for a non-educational program private class GetCredentialsTask extends AsyncTask { ProgressDialog authDialog; @Override protected void onPreExecute() { authDialog = ProgressDialog.show(DetailsTwitter.this, getText(R.string.auth_progress_title), getText(R.string.auth_progress_text), true, // indeterminate duration false); // not cancel-able } @Override protected JSONObject doInBackground(Void... arg0) { JSONObject jso = null; HttpGet get = new HttpGet(VERIFY_URL_STRING); try { mConsumer.sign(get); String response = mClient.execute(get, new BasicResponseHandler()); jso = new JSONObject(response); } catch (OAuthMessageSignerException e) { e.printStackTrace(); } catch (OAuthExpectationFailedException e) { e.printStackTrace(); } catch (OAuthCommunicationException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return jso; } // This is in the UI thread, so we can mess with the UI protected void onPostExecute(JSONObject jso) { authDialog.dismiss(); mCB.setChecked(jso != null); mButton.setEnabled(jso != null); mEditor.setEnabled(jso != null); mUser.setText(jso != null ? getUserName(jso) : getString(R.string.userhint)); mLast.setText(jso != null ? getLastTweet(jso) : getString(R.string.userhint)); if(jso != null) { TimelineSelector ss = new TimelineSelector(HOME_TIMELINE_URL_STRING); new GetTimelineTask().execute(ss); } } } private String getLastTweet(JSONObject credentials) { try { JSONObject status = credentials.getJSONObject("status"); return getCurrentTweet(status); } catch (JSONException e) { e.printStackTrace(); return getString(R.string.tweet_error); } } private String getUserName(JSONObject credentials) { return credentials.optString("name", getString(R.string.bad_value)); } private class TimelineSelector extends Object { public String url; // the url to perform the query from // not all these apply to every url - you are responsible public Long since_id; // ids newer than this will be fetched public Long max_id; // ids older than this will be fetched public Integer count; // # of tweets to fetch Max is 200 public Integer page; // # of page to fetch (with limits) public TimelineSelector(String u) { url = u; max_id = null; since_id = null; count = null; page = null; } @SuppressWarnings("unused") public TimelineSelector(String u, Long since, Long max, Integer cnt, Integer pg) { url = u; max_id = max; since_id = since; count = cnt; page = pg; } } private class UserStatus { JSONObject mStatus; @SuppressWarnings("unused") JSONObject mUser; public UserStatus(JSONObject status) throws JSONException { mStatus = status; mUser = status.getJSONObject("user"); } @SuppressWarnings("unused") public long getId() { return mStatus.optLong("id", -1); } /*public String getUserName() { return mUser.optString("name", getString(R.string.bad_value)); } public String getText() { return getCurrentTweet(mStatus); } public String getCreatedAt() { @SuppressWarnings("unused") Time ret1 = new Time(); return mStatus.optString("created_at", getString(R.string.bad_value)); }*/ } private class GetTimelineTask extends AsyncTask { @Override protected JSONArray doInBackground(TimelineSelector... params) { JSONArray array = null; try { for(int i = 0; i < params.length; ++i) { Uri sUri = Uri.parse(params[i].url); Uri.Builder builder = sUri.buildUpon(); if(params[i].since_id != null) { builder.appendQueryParameter("since_id", String.valueOf(params[i].since_id)); } else if (params[i].max_id != null) { // these are mutually exclusive builder.appendQueryParameter("max_id", String.valueOf(params[i].max_id)); } if(params[i].count != null) { builder.appendQueryParameter("count", String.valueOf((params[i].count > 200) ? 200 : params[i].count)); } if(params[i].page != null) { builder.appendQueryParameter("page", String.valueOf(params[i].page)); } HttpGet get = new HttpGet(builder.build().toString()); mConsumer.sign(get); String response = mClient.execute(get, new BasicResponseHandler()); array = new JSONArray(response); } } catch (JSONException e) { e.printStackTrace(); } catch (OAuthMessageSignerException e) { e.printStackTrace(); } catch (OAuthExpectationFailedException e) { e.printStackTrace(); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (OAuthCommunicationException e) { e.printStackTrace(); } return array; } // This is in the UI thread, so we can mess with the UI protected void onPostExecute(JSONArray array) { if(array != null) { try { for(int i = 0; i < array.length(); ++i) { JSONObject status = array.getJSONObject(i); UserStatus s = new UserStatus(status); mHomeStatus.add(s); } //mAA.notifyDataSetChanged(); } catch (JSONException e) { e.printStackTrace(); } } else { } } } } 

我的AndroidManifest.xml


           

我希望,这应该足以让你前进。

如果这里有问题,请求评论。

问候,

iarwain