Android throwing up Error using jtwitter - java

I am trying to write a twitter application on Android target 2.2 (using some sample code that I found on the net and using Marko Gargenta's O'Reilly text). I am stuck with the problem as in the log below. The source code is given first followed by the log. Any idea what's going wrong here ? Also does anyone have or can point to a sample jtwitter code working on Android.
Thanks,
Ravi
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";
}
}
Log file:
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'
----

Basically the JTwitter library has calls to Java swing classes that are not in the Android SDK as it does not use swing. I had to get the source for JTwitter and remove the swing code for my application to work. Hope this helps.

Might be worth looking at using the Twitter4J library as an alternative. I've had no issues using it within an Android application.

I found most of the code I use somewhere on GitHub (can't find the exact link right now)
A few searches on snippets of the code send me here, but I don't think that was the exact site I got it from.
But this is what I have in my semi-working code.
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 (my "implementation")
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<UserStatus> mHomeStatus = new LinkedList<UserStatus>();
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<String, Void, JSONObject> {
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<BasicNameValuePair> out = new LinkedList<BasicNameValuePair>();
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<Void, Void, JSONObject> {
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<TimelineSelector, Void, JSONArray> {
#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 {
}
}
}
}
My AndroidManifest.xml
<activity android:name="DetailsTwitter" />
<activity android:name="OAUTH" >
<intent-filter>
<action android:name="android.intent.action.VIEW"></action>
<category android:name="android.intent.category.DEFAULT"></category>
<category android:name="android.intent.category.BROWSABLE"></category>
<data android:scheme="gpsagenda" android:host="twitt" />
</intent-filter>
</activity>
This should be enough to get you going, I hope.
If something is wrong in here, pleas do comment.
Regards,
iarwain

Related

Start intensive POST in background service getting crashes

So there is a background Service which creates Runnable objects as soon as GPS Location is changed. Runnable contains HTTPConnection to make POST and twice send broadcast message via sendBroadcast().
So the problem I am facing if there is no chance to send data by this scheme something happened and app craches.
Any clue to refactor code or may be change approach to TaskAsync and cancel pending TaskAsync when new TaskAsync is ready?
Any clue?
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.text.format.DateFormat;
import android.util.Log;
import com.google.gson.Gson;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Date;
public class gps_service2 extends Service {
private static final String TAG = "GPS SERVICE";
private LocationManager mLocationManager = null;
private static final int LOCATION_INTERVAL = 10000;
private static final float LOCATION_DISTANCE = 10f;
Context context;
private class LocationListener implements android.location.LocationListener
{
Location mLastLocation;
public LocationListener(String provider)
{
Log.e(TAG, "LocationListener " + provider);
mLastLocation = new Location(provider);
}
#Override
public void onLocationChanged(Location location)
{
Log.e(TAG, "onLocationChanged: " + location);
try
{
ComplexPreferences complexPreferences = ComplexPreferences.getComplexPreferences(context, "App_Settings", 0);
AppSettings appSettings = complexPreferences.getObject("App_Settings", AppSettings.class);
if (appSettings != null) {
LocationItem locationItem = new LocationItem();
locationItem.DeviceID = appSettings.getDeviceID();
locationItem.Latitude = Double.toString(location.getLatitude());
locationItem.Longitude = Double.toString(location.getLongitude());
Date d = new Date();
CharSequence timeOfRequest = DateFormat.format("yyyy-MM-dd HH:mm:ss", d.getTime()); // YYYY-MM-DD HH:mm:ss
locationItem.TimeOfRequest = timeOfRequest.toString();
locationItem.SerialNumber = appSettings.getSerialNumber();
Gson gson = new Gson();
String requestObject = gson.toJson(locationItem);
String url = appSettings.getIpAddress() + "/api/staff/savedata";
makeRequest(url, requestObject, dLocation);
}
}
catch (Exception ex)
{
}
}
#Override
public void onProviderDisabled(String provider)
{
Log.e(TAG, "onProviderDisabled: " + provider);
}
#Override
public void onProviderEnabled(String provider)
{
Log.e(TAG, "onProviderEnabled: " + provider);
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
Log.e(TAG, "onStatusChanged: " + provider);
}
}
LocationListener[] mLocationListeners = new LocationListener[] {
new LocationListener(LocationManager.GPS_PROVIDER),
new LocationListener(LocationManager.NETWORK_PROVIDER)
};
#Override
public IBinder onBind(Intent arg0)
{
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.e(TAG, "onStartCommand");
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
#Override
public void onCreate()
{
context = this;
Log.e(TAG, "onCreate");
initializeLocationManager();
try {
mLocationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
mLocationListeners[1]);
} catch (java.lang.SecurityException ex) {
Log.i(TAG, "fail to request location update, ignore", ex);
} catch (IllegalArgumentException ex) {
Log.d(TAG, "network provider does not exist, " + ex.getMessage());
}
try {
mLocationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
mLocationListeners[0]);
} catch (java.lang.SecurityException ex) {
Log.i(TAG, "fail to request location update, ignore", ex);
} catch (IllegalArgumentException ex) {
Log.d(TAG, "gps provider does not exist " + ex.getMessage());
}
}
#Override
public void onDestroy()
{
Log.e(TAG, "onDestroy");
super.onDestroy();
if (mLocationManager != null) {
for (int i = 0; i < mLocationListeners.length; i++) {
try {
mLocationManager.removeUpdates(mLocationListeners[i]);
} catch (Exception ex) {
Log.i(TAG, "fail to remove location listners, ignore", ex);
}
}
}
}
private void initializeLocationManager() {
Log.e(TAG, "initializeLocationManager");
if (mLocationManager == null) {
mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
}
}
public static double round(double value, int places) {
if (places < 0) throw new IllegalArgumentException();
BigDecimal bd = new BigDecimal(value);
bd = bd.setScale(places, RoundingMode.HALF_UP);
return bd.doubleValue();
}
public void makeRequest(String uri, String json, DLocation dLocation) {
HandlerThread handlerThread = new HandlerThread("URLConnection");
handlerThread.start();
Handler mainHandler = new Handler(handlerThread.getLooper());
Runnable myRunnable = createRunnable(uri, json, dLocation);
mainHandler.post(myRunnable);
}
private Runnable createRunnable(final String uri, final String data,final DLocation dLocation){
Runnable aRunnable = new Runnable(){
public void run(){
try {
//Connect
HttpURLConnection urlConnection;
urlConnection = (HttpURLConnection) ((new URL(uri).openConnection()));
urlConnection.setDoOutput(true);
urlConnection.setRequestProperty("Content-Type", "application/json");
urlConnection.setRequestProperty("Accept", "application/json");
urlConnection.setRequestMethod("POST");
urlConnection.connect();
//Write
OutputStream outputStream = urlConnection.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8"));
try {
writer.write(data);
} catch (IOException e) {
e.printStackTrace();
Log.d(TAG,"Ошибка записи в буфер для пережачи по HTTP");
}
writer.close();
outputStream.close();
//Read
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "UTF-8"));
String line = null;
StringBuilder sb = new StringBuilder();
while ((line = bufferedReader.readLine()) != null) {
sb.append(line);
}
bufferedReader.close();
String result = sb.toString();
Log.d(TAG, result);
Intent iResult = new Intent("location_update");
DLocation dLocation = new DLocation();
iResult.putExtra("result", dLocation);
sendBroadcast(iResult);
}catch( Exception err){
err.printStackTrace();
Log.d(TAG, "HTTP " + err.getMessage());
}
}
};
return aRunnable;
}
}
Runnable is just an interface, when you create a thread using Runnable interface basically it will run under the the thread where it created, in here runnable associate with UI thread, as per google documentation Network calls must be in a worker thread not in UI thread.
Then Why it runs on emulator
android had DVM(dalvik virtual machine),it works like JVM but instead of .class file DVM uses .dex extension, so may the device had older or newer version of DVM.
Fix
Use android's AsyncTask for network calls. android(DVM) had limited resources compare to JVM, when it comes to thread, so better use AsyncTask
check this answer too
AsyncTask code for passing JSON to server, and get responds as callback
public class WebService extends AsyncTask<String,String,String> {
private static final String TAG="SyncToServerTAG";
private String urlString;
private JSONObject jsonObject=null;
private int screenId=1;
public WebService(String url) {
this.urlString=url;
}
public WebService(Context context, String url, JSONObject jsonObject) {
this.urlString = url;
this.jsonObject = jsonObject;
}
#Override
protected String doInBackground(String... strings) {
try {
URL url = new URL(urlString);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setChunkedStreamingMode(0);
urlConnection.setConnectTimeout(5000);
urlConnection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
urlConnection.setDoOutput(true);
urlConnection.setDoInput(true);
urlConnection.setRequestMethod("POST");
if(jsonObject!=null) {
OutputStream os = urlConnection.getOutputStream();
os.write(jsonObject.toString().getBytes("UTF-8"));
}
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
BufferedReader br = new BufferedReader(new InputStreamReader(
(urlConnection.getInputStream())));
String output="";
while (true) {
String line=br.readLine();
Log.d(TAG,line+" ");
if(line!=null)
output+=line;
else
break;
}
in.close();
urlConnection.disconnect();
JSONObject j;
if(output.equals(""))
publishProgress("Server give null");
else {
j=new JSONObject(output);
return output;
}
return output;
} catch (MalformedURLException e) {
e.printStackTrace();
publishProgress(e.toString());
} catch (IOException e) {
e.printStackTrace();
publishProgress(e.toString());
} catch (JSONException e) {
e.printStackTrace();
publishProgress(e.toString());
}
return null;
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
fireError(values[0]);
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
if(s!=null) {
try {
JSONObject jsonObject=new JSONObject(s);
fireComplete(0, jsonObject);
} catch (JSONException e) {
e.printStackTrace();
fireError("Non acceptable responds from server ["+urlString+"]");
}
}
}
public interface OnWebCompleteListener{
void onComplete(JSONObject result, int dataSource);
void onError(String error);
}
private OnWebCompleteListener onWebCompleteListener;
private void fireComplete(int sourse,JSONObject cache){
if(onWebCompleteListener!=null)
onWebCompleteListener.onComplete(cache,sourse);
}
private void fireError(String message){
if(onWebCompleteListener!=null)
onWebCompleteListener.onError(message);
}
public void start(OnWebCompleteListener onWebCompleteListener){
if(onWebCompleteListener==null)
throw new RuntimeException("You must provide non-null value as start listener");
this.onWebCompleteListener=onWebCompleteListener;
execute((String)null);
}
}
Usage
WebService webService=new WebService(context,"url",jsonObject);
webService.start(new WebService.OnWebCompleteListener() {
#Override
public void onComplete(JSONObject result, int dataSource) {
}
#Override
public void onError(String error) {
}
});
Your code is very vulnerable. I think that you crash because your makeRequest method exits before you Runnable had the chance to complete the task.
You closed the resource as soon as you send them, freeing system resources.
There for the second time you call broadcast, the resources are not there anymore causing the crash....

java.io.IOException: bt socket closed, read return: -1

As i am working on OBD Reader Demo .Through my app i am trying to connect obd reader device and my app is installed in Nexus 7.OBD Reader device is connecting to other apps which is available on google play but if i am connecting with my app it is getting error java.io.IOException: bt socket closed, read return: -1 after connection establish .Any suggestions...
=========================================================
**MainActivity:-**
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Set;
import java.util.UUID;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.virgosys.demo.commands.SpeedObdCommand;
import com.virgosys.demo.commands.engine.EngineRPMObdCommand;
import com.virgosys.demo.commands.fuel.FindFuelTypeObdCommand;
public class MainActivity extends Bluetooth {
#SuppressWarnings("unused")
private Button On, Off, Visible, list;
private BluetoothAdapter BA;
private Set<BluetoothDevice> pairedDevices;
#SuppressWarnings("unused")
private ListView lv;
private BluetoothDevice device;
// private UUID uuid;
// private BluetoothSocketWrapper bluetoothSocket;
private BluetoothSocket socket;
private String deviceAddress;
String RPM, Speed, FuelType;
private TextView uuidTextView, deviceTextView, showRpm, showSpeed,
showFuelType, tv_connection_e, tv_connection_f;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
showRpm = ((TextView) findViewById(R.id.show_rpm));
showSpeed = ((TextView) findViewById(R.id.txt_speed));
showFuelType = ((TextView) findViewById(R.id.txt_fueltype));
uuidTextView = ((TextView) findViewById(R.id.txt_uuid));
deviceTextView = ((TextView) findViewById(R.id.txt_device));
// tv_connection_e = ((TextView) findViewById(R.id.txt_device));
// tv_connection_f = ((TextView) findViewById(R.id.show_error));
On = (Button) findViewById(R.id.button1);
Off = (Button) findViewById(R.id.button2);
Visible = (Button) findViewById(R.id.button3);
list = (Button) findViewById(R.id.button4);
lv = (ListView) findViewById(R.id.listView1);
BA = BluetoothAdapter.getDefaultAdapter();
try {
Process process = Runtime.getRuntime().exec("logcat -d");
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
StringBuilder log = new StringBuilder();
String line = "";
while ((line = bufferedReader.readLine()) != null) {
log.append(line);
}
TextView tv_connection_e = (TextView) findViewById(R.id.show_error);
tv_connection_e.setText(log.toString());
} catch (IOException e) {
}
}
public void on(View view) {
if (!BA.isEnabled()) {
Intent turnOn = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(turnOn, 0);
Toast.makeText(getApplicationContext(), "Turned on",
Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(), "Already on",
Toast.LENGTH_LONG).show();
}
}
#SuppressWarnings("unchecked")
public void list(View view) {
ArrayList deviceStrs = new ArrayList();
final ArrayList devices = new ArrayList();
BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
pairedDevices = btAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
deviceStrs.add(device.getName() + "\n" + device.getAddress());
devices.add(device.getAddress());
}
}
// show list
final AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
ArrayAdapter adapter = new ArrayAdapter(this,
android.R.layout.select_dialog_singlechoice,
deviceStrs.toArray(new String[deviceStrs.size()]));
alertDialog.setSingleChoiceItems(adapter, -1,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
int position = ((AlertDialog) dialog).getListView()
.getCheckedItemPosition();
deviceAddress = (String) devices.get(position);
System.out.println("Device Address-->" + deviceAddress);
/*
* Intent i = new Intent(MainActivity.this,
* SecondActivity.class); i.putExtra("uuid",
* "00001101-0000-1000-8000-00805F9B34FB");
* i.putExtra("deviceAddress", deviceAddress);
* i.putExtra("RPM", RPM); i.putExtra("Speed", Speed);
* startActivity(i);
*/
try {
dothings();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// save deviceAddress
}
});
alertDialog.setTitle("Choose Bluetooth device");
alertDialog.show();
}
#SuppressLint("NewApi")
protected void dothings() throws InterruptedException {
System.out.println("Inside Do things");
System.out.println("Device address in Do things -->" + deviceAddress);
device = BA.getRemoteDevice(deviceAddress);
// UUID SERIAL_UUID = device.getUuids()[0].getUuid();
// uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
System.out.println("Device Name-->" + device.getName());
System.out.println("Device Address-->" + device.getAddress());
System.out.println("Device Bond State-->" + device.getBondState());
System.out.println("Device Type-->" + device.getType());
System.out.println("Device UUIDS-->" + device.getUuids());
ConnectThread t = new ConnectThread(device);
t.start();
showRpm.setText(RPM);
showSpeed.setText(Speed);
showFuelType.setText(FuelType);
uuidTextView.setText("00001101-0000-1000-8000-00805F9B34FB");
deviceTextView.setText(deviceAddress);
}
public void off(View view) {
BA.disable();
Toast.makeText(getApplicationContext(), "Turned off", Toast.LENGTH_LONG)
.show();
}
public void visible(View view) {
Intent getVisible = new Intent(
BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
startActivityForResult(getVisible, 0);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final UUID WELL_KNOWN_UUID = UUID
.fromString("00001101-0000-1000-8000-00805f9b34fb");
private Object e;
public ConnectThread(BluetoothDevice device) {
// Use a temporary object that is later assigned to mmSocket,because
// mmSocket is final
BluetoothSocket tmp = null;
// Get a BluetoothSocket to connect with the given BluetoothDevice
try {
tmp = device.createRfcommSocketToServiceRecord(WELL_KNOWN_UUID);
// This is the trick
Method m = device.getClass().getMethod("createRfcommSocket",
new Class[] { int.class });
tmp = (BluetoothSocket) m.invoke(device, 1);
} catch (Exception e) {
e.printStackTrace();
}
mmSocket = tmp;
}
public void run() {
System.out.println("Trying to connect...");
// Cancel discovery because it will slow down the connection
BA.cancelDiscovery();
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
mmSocket.connect();
System.out.println("Connection established");
// tv_connection_e.setText(e.print.stacktrace);
ConnectedThread tc = new ConnectedThread(mmSocket);
tc.start();
} catch (IOException connectException) {
// Unable to connect; close the socket and get out
System.out.println("Fail to connect!");
try {
mmSocket.close();
} catch (IOException closeException) {
System.out.println("Fail to close connection");
}
return;
}
}
/** Will cancel an in-progress connection, and close the socket */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
}
}
}
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
}
System.out.println("Inside the thread");
mmInStream = tmpIn;
mmOutStream = tmpOut;
try {
EngineRPMObdCommand engineRpmCommand = new EngineRPMObdCommand();
SpeedObdCommand speedCommand = new SpeedObdCommand();
FindFuelTypeObdCommand fueltypeCommand = new FindFuelTypeObdCommand();
System.out.println("Inside the try block");
while (!Thread.currentThread().isInterrupted()) {
System.out.println("Inside while");
// TODO handle commands result
Log.d("Poonam",
"RPM: " + engineRpmCommand.getFormattedResult());
Log.d("Poonam",
"Speed: " + speedCommand.getFormattedResult());
Log.d("Poonam",
"FuelType: " + fueltypeCommand.getFormattedResult());
RPM = engineRpmCommand.getFormattedResult();
Speed = speedCommand.getFormattedResult();
FuelType = fueltypeCommand.getFormattedResult();
try {
engineRpmCommand.run(mmInStream, mmOutStream);
speedCommand.run(mmInStream, mmOutStream);
fueltypeCommand.run(mmInStream, mmOutStream);
System.out.println("Commands Processed");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("outside try catch");
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("inside catch before while");
}
// Get the input and output streams, using temp objects because
// member streams are final
}
public void run() {
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
}
}
/* Call this from the main activity to send data to the remote device */
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) {
}
}
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
}
}
}
}
**Bluetooth.java**
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.util.Log;
public class Bluetooth extends Activity{
private BluetoothSocketWrapper bluetoothSocket;
private BluetoothDevice device;
private boolean secure;
private BluetoothAdapter adapter;
private List<UUID> uuidCandidates;
private int candidate;
/**
* #param device the device
* #param secure if connection should be done via a secure socket
* #param adapter the Android BT adapter
* #param uuidCandidates a list of UUIDs. if null or empty, the Serial PP id is used
* #return
*/
public void BluetoothConnector(BluetoothDevice device, boolean secure, BluetoothAdapter adapter,
List<UUID> uuidCandidates) {
this.device = device;
this.secure = secure;
this.adapter = adapter;
this.uuidCandidates = uuidCandidates;
if (this.uuidCandidates == null || this.uuidCandidates.isEmpty()) {
this.uuidCandidates = new ArrayList<UUID>();
this.uuidCandidates.add(UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"));
}
}
public BluetoothSocketWrapper connect() throws IOException {
boolean success = false;
while (selectSocket()) {
adapter.cancelDiscovery();
try {
bluetoothSocket.connect();
success = true;
break;
} catch (IOException e) {
//try the fallback
try {
bluetoothSocket = new FallbackBluetoothSocket(bluetoothSocket.getUnderlyingSocket());
Thread.sleep(500);
bluetoothSocket.connect();
success = true;
break;
} catch (FallbackException e1) {
Log.w("BT", "Could not initialize FallbackBluetoothSocket classes.", e);
} catch (InterruptedException e1) {
Log.w("BT", e1.getMessage(), e1);
} catch (IOException e1) {
Log.w("BT", "Fallback failed. Cancelling.", e1);
}
}
}
if (!success) {
throw new IOException("Could not connect to device: "+ device.getAddress());
}
return bluetoothSocket;
}
private boolean selectSocket() throws IOException {
if (candidate >= uuidCandidates.size()) {
return false;
}
BluetoothSocket tmp = null;
UUID uuid = uuidCandidates.get(candidate++);
Log.i("BT", "Attempting to connect to Protocol: "+ uuid);
if (secure) {
Method m = null;
try {
m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
tmp = (BluetoothSocket) m.invoke(device, 1);
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
tmp = device.createInsecureRfcommSocketToServiceRecord(uuid);
}
bluetoothSocket = new NativeBluetoothSocket(tmp);
return true;
}
public static interface BluetoothSocketWrapper {
InputStream getInputStream() throws IOException;
OutputStream getOutputStream() throws IOException;
String getRemoteDeviceName();
void connect() throws IOException;
String getRemoteDeviceAddress();
void close() throws IOException;
BluetoothSocket getUnderlyingSocket();
}
public static class NativeBluetoothSocket implements BluetoothSocketWrapper {
private BluetoothSocket socket;
public NativeBluetoothSocket(BluetoothSocket tmp) {
this.socket = tmp;
}
#Override
public InputStream getInputStream() throws IOException {
return socket.getInputStream();
}
#Override
public OutputStream getOutputStream() throws IOException {
return socket.getOutputStream();
}
#Override
public String getRemoteDeviceName() {
return socket.getRemoteDevice().getName();
}
#Override
public void connect() throws IOException {
socket.connect();
}
#Override
public String getRemoteDeviceAddress() {
return socket.getRemoteDevice().getAddress();
}
#Override
public void close() throws IOException {
socket.close();
}
#Override
public BluetoothSocket getUnderlyingSocket() {
return socket;
}
}
public class FallbackBluetoothSocket extends NativeBluetoothSocket {
private BluetoothSocket fallbackSocket;
public FallbackBluetoothSocket(BluetoothSocket tmp) throws FallbackException {
super(tmp);
try
{
Class<?> clazz = tmp.getRemoteDevice().getClass();
Class<?>[] paramTypes = new Class<?>[] {Integer.TYPE};
Method m = clazz.getMethod("createRfcommSocket", paramTypes);
Object[] params = new Object[] {Integer.valueOf(1)};
fallbackSocket = (BluetoothSocket) m.invoke(tmp.getRemoteDevice(), params);
}
catch (Exception e)
{
throw new FallbackException(e);
}
}
#Override
public InputStream getInputStream() throws IOException {
return fallbackSocket.getInputStream();
}
#Override
public OutputStream getOutputStream() throws IOException {
return fallbackSocket.getOutputStream();
}
#Override
public void connect() throws IOException {
fallbackSocket.connect();
}
#Override
public void close() throws IOException {
fallbackSocket.close();
}
}
public static class FallbackException extends Exception {
/**
*
*/
private static final long serialVersionUID = 1L;
public FallbackException(Exception e) {
super(e);
}
}
}
(MainActivity.java:367)
try {
engineRpmCommand.run(mmInStream, mmOutStream);
speedCommand.run(mmInStream, mmOutStream);
fueltypeCommand.run(mmInStream, mmOutStream);
System.out.println("Commands Processed");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
367--> e.printStackTrace();
}
System.out.println("outside try catch");
}
(ObdCommand.java:164)
protected void readRawData(InputStream in) throws IOException {
byte b = 0;
StringBuilder res = new StringBuilder();
// read until '>' arrives
164--> while ((char) (b = (byte) in.read()) != '>')
res.append((char) b);
Have you checked if your string builder / buffer contains anything at the time the exception is thrown?
I've had this trouble with Bluetooth on a Nexus 7 2012 and the only thing I can suggest is that you Thread.sleep() while waiting for data and use .available() from the stream to make sure you don't read more than what is available.
You could sleep loop while .available() is zero and not equal to the amount as the last loop, and then assume you have all the data when it stabilizes. Alternatively you can simply catch the exception and assume you have received all the data at that point.
I think its a bug in read() method. From #Keilaron's answer.. I tried this and this works:
while (inputStream.available() == 0);
val available = inputStream.available()
val bytes = ByteArray(available)
inputStream.read(bytes, 0, available)
val text = String(bytes)

Why I am getting java.lang.NullPointerException?

I am trying to test this script, to get print some demo text to my Zebra printer using Android, but I am getting a java.lang.NullPointerException. I have read is something about an initialization, but I can't identify what is the object to initializate.
this is the error:
E/AndroidRuntime(2098):
FATAL EXCEPTION: Thread-9874
Process: com.stihn.sibmovil, PID: 2098
java.lang.NullPointerException
at com.stihn.sibmovil.sendfile.SibPrint.testSendFile(SibPrint.java:88)
at com.stihn.sibmovil.sendfile.SibPrint.access$0(SibPrint.java:86)
at com.stihn.sibmovil.sendfile.SibPrint$1.run(SibPrint.java:53)
at java.lang.Thread.run(Thread.java:841)
Thanks for your help!
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import android.os.Looper;
import com.stihn.sibmovil.util.SettingsHelper;
import com.zebra.sdk.comm.BluetoothConnection;
import com.zebra.sdk.comm.Connection;
import com.zebra.sdk.comm.ConnectionException;
import com.zebra.sdk.printer.ZebraPrinter;
import com.zebra.sdk.printer.ZebraPrinterFactory;
import com.zebra.sdk.printer.ZebraPrinterLanguageUnknownException;
import org.apache.cordova.api.Plugin;
import org.apache.cordova.api.PluginResult;
import com.zebra.sdk.printer.PrinterLanguage;
import org.json.JSONArray;
import org.json.JSONException;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
public class SibPrint extends Plugin {
ProgressDialog loadingDialog;
Activity activity;
private Context context;
String macAddress;
String filepath;
public PluginResult execute(String action, JSONArray args, String callbackId) {
try {
if (action.equals("sibPrintTicket")) {
String echo = args.getString(0);
filepath = args.getString(1);
macAddress = args.getString(2);
if (echo != null && echo.length() > 0) {
new Thread(new Runnable() {
public void run() {
Looper.prepare();
Connection connection = null;
connection = new BluetoothConnection(macAddress);
try {
System.out.println("Imprimiendo ...");
connection.open();
ZebraPrinter printer = ZebraPrinterFactory
.getInstance(connection);
testSendFile(printer);
connection.close();
} catch (ConnectionException e) {
System.out.println("Error Try 1 "
+ e.getMessage());
} catch (ZebraPrinterLanguageUnknownException e) {
System.out.println("Error Catch 1 "
+ e.getMessage());
} finally {
if (activity != null && loadingDialog != null) {
loadingDialog.dismiss();
}
}
Looper.loop();
Looper.myLooper().quit();
}
}).start();
//retornar mensaje de imprimiendo
return new PluginResult(PluginResult.Status.OK, "Imprimiendo..");
} else {
return new PluginResult(PluginResult.Status.ERROR);
}
} else {
return new PluginResult(PluginResult.Status.INVALID_ACTION);
}
} catch (JSONException e) {
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
}
}
private void testSendFile(ZebraPrinter printer) {
try {
File filepath = context.getFileStreamPath("TEST.LBL");
createDemoFile(printer, "TEST.LBL");
printer.sendFileContents(filepath.getAbsolutePath());
this.saveBluetoothAddress(this, macAddress);
} catch (ConnectionException e1) {
System.out.println("Error sending file to printer" + e1.getMessage());
} catch (IOException e) {
System.out.println("Error creating file" + e.getMessage());
}
}
private void saveBluetoothAddress(SibPrint sibPrint,
String macAddress) {
// TODO Auto-generated method stub
}
private void createDemoFile(ZebraPrinter printer, String fileName) throws IOException {
FileOutputStream os = context.openFileOutput(fileName, Context.MODE_PRIVATE);
byte[] configLabel = null;
PrinterLanguage pl = printer.getPrinterControlLanguage();
if (pl == PrinterLanguage.ZPL) {
configLabel = "^XA^FO17,16^GB379,371,8^FS^FT65,255^A0N,135,134^FDTEST^FS^XZ".getBytes();
} else if (pl == PrinterLanguage.CPCL) {
String cpclConfigLabel = "! 0 200 200 406 1\r\n" + "ON-FEED IGNORE\r\n" + "BOX 20 20 380 380 8\r\n" + "T 0 6 137 177 TEST\r\n" + "PRINT\r\n";
configLabel = cpclConfigLabel.getBytes();
}
os.write(configLabel);
os.flush();
os.close();
}
}
you got java.lang.NullPointerException in Context
at
File filepath = context.getFileStreamPath("TEST.LBL");
you are not initialize context in your class.
please add
public void SibPrint(Context context){
this.context=context;
}
in your class.
and create consructor in Activity like
SibPrint mSibPrint = new SibPrint(MyActivity.this);
public class SibPrint extends Plugin {
ProgressDialog loadingDialog;
Activity activity;
private Context context;
String macAddress;
String filepath;
//add this method
public void SibPrint(Context context){
this.context=context;
}
.
.
.
}
Try this..
You have not initialize context that's inside testSendFile() method
File filepath = context.getFileStreamPath("TEST.LBL");
you should initialize context before using it otherwise you will get NPE

Android USB to Serial Receive Error

I'm currently working on writing an App on Android to interface with an Arduino Board. I am able to send serial data to my Arduino just fine, however my app crashes at start up the moment I begin trying to receive data.
I currently have it set so a text field takes data from a user, and sends to the Arduino, Arduino does a function.
For my receive, I am making a new thread at start up to constantly listen for data from the Arduino. whenever the code in this thread is executed, it crashes.
I am using this library as my basis: https://github.com/mik3y/usb-serial-for-android
Below is the all the code pertinent, omitted code for other functionality this app is providing, that are unrealted:
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import com.hoho.android.usbserial.driver.UsbSerialDriver;
import android.hardware.usb.UsbManager;
import android.content.Intent;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.content.Context;
import android.util.Log;
import com.hoho.android.usbserial.driver.UsbSerialProber;
public class MainActivity extends Activity implements SensorEventListener, LocationListener{
private EditText sendTextField;
TextView uartRX;
public Handler Handler;
UsbManager manager;
/** Called to create application activity*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
uartRX = (TextView)findViewById(R.id.rxUART);
sendTextField = (EditText) findViewById(R.id.sendTextField);
Handler = new Handler() {
#Override public void handleMessage(Message msg) {
String text = (String)msg.obj;
uartRX.append(text);
}
};
Thread t = new Thread(new Runnable() {
public void run()
{
Message msg = new Message();
msg.obj = "Start Serial Listen\n";
Handler.sendMessage(msg);
rxUART();
}
public void rxUART()
{
manager = (UsbManager) getSystemService(Context.USB_SERVICE);
UsbSerialDriver rxDriver = UsbSerialProber.acquire(manager);
if (rxDriver != null) {
try {
rxDriver.open();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
int byteSize = 0;
String data = "";
while(true)
{
byte[] arr = null;
try {
rxDriver.setBaudRate(115200);
rxDriver.read(arr, byteSize);
data = new String(arr);
Message msg = new Message();
msg.obj = data;
Handler.sendMessage(msg);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
t.start();
}
public void sendUART(String data)
{
manager = (UsbManager) getSystemService(Context.USB_SERVICE);
// Find the first available driver.
UsbSerialDriver driver = UsbSerialProber.acquire(manager);
if (driver != null) {
try {
driver.open();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
driver.setBaudRate(115200);
byte buffer[] = new byte[16];
int numBytesRead = driver.read(buffer, 1000);
Log.d(TAG, "Read " + numBytesRead + " bytes.");
byte temp[] = data.getBytes();
driver.write(temp, 16);
} catch (IOException e) {
// Deal with error.
} finally {
try {
driver.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public void onClickSendBtn(View v)
{
String data = "";
data = sendTextField.getText().toString();
sendUART(data);
sendTextField.setText(" ");
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
Can anyone help me figure out why the app crashes on the code created in the thread?
Note: the code also crashes when not in a thread. Code was originally a function called by sendUART() to check for a response. no while(true) either.
Logcat:
11-02 09:49:22.988: E/AndroidRuntime(22652): FATAL EXCEPTION: Thread-964
11-02 09:49:22.988: E/AndroidRuntime(22652): java.lang.NullPointerException
11-02 09:49:22.988: E/AndroidRuntime(22652): at com.example.sensortest.MainActivity$2.rxUART(MainActivity.java:143)
11-02 09:49:22.988: E/AndroidRuntime(22652): at com.example.sensortest.MainActivity$2.run(MainActivity.java:119)
11-02 09:49:22.988: E/AndroidRuntime(22652): at java.lang.Thread.run(Thread.java:856)
The line numbers referenced are:
Thread t = new Thread(new Runnable() {
public void run()
{
Message msg = new Message();
msg.obj = "Start Serial Listen\n";
Handler.sendMessage(msg);
rxUART();
}
public void rxUART()
{
manager = (UsbManager) getSystemService(Context.USB_SERVICE);
UsbSerialDriver rxDriver = UsbSerialProber.acquire(manager);
if (rxDriver != null) {
try {
rxDriver.open();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
int byteSize = 0;
String data = "";
while(true)
{
byte[] arr = null;
try {
rxDriver.setBaudRate(115200);
rxDriver.read(arr, byteSize);
data = new String(arr);
Message msg = new Message();
msg.obj = data;
Handler.sendMessage(msg);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
t.start();
You don't handle the case rxDriver == null in rxUart() correctly.
The if() statement skips the open() call only, but the while() loop gets executed with rxDriver being NULL resulting in NPE. You have the same problem in `sendUART(), btw.

Android read json from restful service

I am trying to get a response from a service (the response comes in json).
I made my checks if the device is connected and now I need to make the http request to the service. I found out on other questions that I have to use a background thread but I am not sure I got a working sample.
So I need to find out how I can make a connection to a given uri and read the response.
My service needs to get a content header application/json in orderto return a json, so before the request I need to set this header as well.
Thank you in advance
UPDATE
package com.example.restfulapp;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.provider.Settings;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.concurrent.ExecutionException;
public class MainActivity extends Activity {
private int code = 0;
private String value = "";
private ProgressDialog mDialog;
private Context mContext;
private String mUrl ="http://192.168.1.13/myservice/upfields/";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (!isOnline())
{
displayNetworkOption ("MyApp", "Application needs network connectivity. Connect now?");
}
try {
JSONObject s = getJSON(mUrl);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
public class Get extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... arg) {
String linha = "";
String retorno = "";
mDialog = ProgressDialog.show(mContext, "Please wait", "Loading...", true);
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(mUrl);
try {
HttpResponse response = client.execute(get);
StatusLine statusLine = response.getStatusLine();
int statusCode = statusLine.getStatusCode();
if (statusCode == 200) { // Ok
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
while ((linha = rd.readLine()) != null) {
retorno += linha;
}
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return retorno;
}
#Override
protected void onPostExecute(String result) {
mDialog.dismiss();
}
}
public JSONObject getJSON(String url) throws InterruptedException, ExecutionException {
setUrl(url);
Get g = new Get();
return createJSONObj(g.get());
}
private void displayNetworkOption(String title, String message){
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder
.setTitle(title)
.setMessage(message)
.setPositiveButton("Wifi", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
}
})
.setNeutralButton("Data", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
startActivity(new Intent(Settings.ACTION_DATA_ROAMING_SETTINGS));
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
return;
}
})
.show();
}
private boolean isOnline() {
ConnectivityManager cm =
(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
if (netInfo != null && netInfo.isConnectedOrConnecting()) {
return true;
}
return false;
}
}
This throws errors:
Gradle: cannot find symbol method setUrl(java.lang.String)
Gradle: cannot find symbol method createJSONObj(java.lang.String)
After derogatory responses from EvZ who think that he was born knowing everything, I ended up with a subclass MyTask that I call like this inside the onCreate of my Activity.
new MyTask().execute(wserviceURL);
private class MyTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
URL myurl = null;
try {
myurl = new URL(urls[0]);
} catch (MalformedURLException e) {
e.printStackTrace();
}
URLConnection connection = null;
try {
connection = myurl.openConnection();
} catch (IOException e) {
e.printStackTrace();
}
connection.setConnectTimeout(R.string.TIMEOUT_CONNECTION);
connection.setReadTimeout(R.string.TIMEOUT_CONNECTION);
HttpURLConnection httpConnection = (HttpURLConnection) connection;
httpConnection.setRequestProperty("Content-Type", getString(R.string.JSON_CONTENT_TYPE));
int responseCode = -1;
try {
responseCode = httpConnection.getResponseCode();
} catch (SocketTimeoutException ste) {
ste.printStackTrace();
}
catch (Exception e1) {
e1.printStackTrace();
}
if (responseCode == HttpURLConnection.HTTP_OK) {
StringBuilder answer = new StringBuilder(100000);
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(httpConnection.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
String inputLine;
try {
while ((inputLine = in.readLine()) != null) {
answer.append(inputLine);
answer.append("\n");
}
} catch (IOException e) {
e.printStackTrace();
}
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
httpConnection.disconnect();
return answer.toString();
}
else
{
//connection is not OK
httpConnection.disconnect();
return null;
}
}
#Override
protected void onPostExecute(String result) {
String userid = null;
String username = null;
String nickname = null;
if (result!=null)
{
try {
//do read the JSON here
} catch (JSONException e) {
e.printStackTrace();
}
}
//stop loader dialog
mDialog.dismiss();
}
}
lory105's answer guided me to somewhere near the answer, thanx.
here is an example of how to process the HTTP response and convert to JSONObject:
/**
* convert the HttpResponse into a JSONArray
* #return JSONObject
* #param response
* #throws IOException
* #throws IllegalStateException
* #throws UnsupportedEncodingException
* #throws Throwable
*/
public static JSONObject processHttpResponse(HttpResponse response) throws UnsupportedEncodingException, IllegalStateException, IOException {
JSONObject top = null;
StringBuilder builder = new StringBuilder();
try {
BufferedReader reader = new BufferedReader(
new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
for (String line = null; (line = reader.readLine()) != null;) {
builder.append(line).append("\n");
}
String decoded = new String(builder.toString().getBytes(), "UTF-8");
Log.d(TAG, "decoded http response: " + decoded);
JSONTokener tokener = new JSONTokener(Uri.decode(builder.toString()));
top = new JSONObject(tokener);
} catch (JSONException t) {
Log.w(TAG, "<processHttpResponse> caught: " + t + ", handling as string...");
} catch (IOException e) {
Log.e(TAG, "caught: " + e, e);
} catch (Throwable t) {
Log.e(TAG, "caught: " + t, t);
}
return top;
}
From Android 3+, the http connections must be done within a separate thread. Android offers a Class named AsyncTask that help you do it.
Here you can find a good example of an AsyncTask that performs an http request and receives a JSON response.
Remember that in the doInBackgroud(..) method you CAN'T modify the UI such as to launch a Toast, to change activity or others. You have to use the onPreExecute() or onPostExecute() methods to do this.
ADD
For the mDialog and mContext variables, add the code below, and when you create the JSONTask write new JSONTask(YOUR_ACTIVITY)
public abstract class JSONTask extends AsyncTask<String, Void, String> {
private Context context = null;
ProgressDialog mDialog = new ProgressDialog();
public JSONTask(Context _context){ context=_context; }
..

Categories