DalvikVm could not found class android library project - android

Need to tap the collective brain power here. I am trying out a very simple BindService and communicate with Messenger example. Since I am passing message object in the Message.obj field I defined messages in their own Android library project to be shared between service and the client. I can compile fine by including the message library as a depdendency but during runtime dalvikvm complains it could not find class. I have read other related issue dealing with export and orders but same solution doesn't help in my case. It must be a very simple mistake but I am pulling my hair out right now.
App depends on SupportServiceMessageLibrary.
App has library before its src in project's order tab.
Lib is not checked for export in App since no one is consuming the App
Library is exporting its src and gen folder.
The error message from log cat:
01-31 01:53:41.134: E/dalvikvm(22886): Could not find class 'com.example.service.RequestStatus', referenced from method com.example.MainActivity$ServiceReplyHandler.handleMessage
Here are snippet of code
MainActivity
package com.example;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.view.Menu;
import android.widget.TextView;
import com.example.appserver.R;
import com.example.service.MessageType;
import com.example.service.RequestStatus;
public class MainActivity extends Activity {
private TextView serverStatus;
/** Messenger for sending message to service. */
Messenger mServiceMessenger = null;
/** Flag indicating whether we have called bind on the service. */
boolean mBound;
/** Messenger for receiving message from service */
Messenger mClientMessenger = null;
class ServiceReplyHandler extends Handler {
#Override
public void handleMessage(Message msg) {
if (msg.what == MessageType.MSG_REPLY) {
RequestStatus reqStatus = (RequestStatus) msg.obj;
}
}
}
/**
* Class for interacting with the main interface of the service.
*/
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
// This is called when the connection with the service has been
// established, giving us the object we can use to
// interact with the service. We are communicating with the
// service using a Messenger, so here we get a client-side
// representation of that from the raw IBinder object.
mServiceMessenger = new Messenger(service);
Message regMsg = Message.obtain(null,
MessageType.MSG_REGISTER);
regMsg.replyTo = mClientMessenger;
try {
mServiceMessenger.send(regMsg);
} catch (RemoteException e) {
}
mBound = true;
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
mServiceMessenger = null;
mBound = false;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_server);
serverStatus = (TextView) findViewById(R.id.server_status);
Intent startServiceIntent = new Intent();
startServiceIntent.setComponent(new ComponentName(
"com.example.supportservices",
"com.example.service.EntitlementService"));
bindService(startServiceIntent, mConnection, Context.BIND_AUTO_CREATE);
// Initialize messenger to receiver service messages;
mClientMessenger = new Messenger(new ServiceReplyHandler());
}
#Override
protected void onStop() {
super.onStop();
}
#Override
protected void onStart() {
super.onStart();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.server, menu);
return true;
}
}
And the message itself
package com.example.service;
import org.json.JSONException;
import org.json.JSONObject;
import android.text.TextUtils;
public class RequestStatus {
public static int REQUEST_SUCCESS = 0;
public static int REQUEST_FAILURE = 1;
public static String TYPE = "request_status";
public static String STATUS_JSON_KEY = "status";
private int status;
public RequestStatus(int status) {
this.status = status;
}
public static RequestStatus fromJson(String json) {
try {
JSONObject msg = new JSONObject(json);
String type = msg.getString("type");
if (TextUtils.isEmpty(type) || TYPE.equals(type) == false) {
return null;
}
return(new RequestStatus(msg.getJSONObject("body").getInt(STATUS_JSON_KEY)));
} catch (JSONException e) {
return null;
}
}
public String toJson() {
JSONObject msg = new JSONObject();
try {
msg.put("type", TYPE);
JSONObject body = new JSONObject();
body.put(STATUS_JSON_KEY, status);
msg.put("body", body);
} catch (JSONException e) {
return null;
}
return msg.toString();
}
}

Go to project property of the App and add it as a library under Android in addition to project dependency under build path.

Related

Android Wear DataMap onDataChanged() not called for data from other device only

I'm making a library that uses Android Wear's DataMap Api to send information between a Wear device and a phone. I've got the DataMap Api working with another project, but despite using the same steps, it doesn't seem to work in this one. If I use putDataItem on the wear device, or the phone, onDataChanged is only called on the device that changed the data, not the other device.
I've looked everywhere else I could find. I've included a timestamp in my data to make sure the data changes, I've set the PutDataRequest as Urgent with setUrgent() to make sure it gets sent immediately, and I've made sure the onResult returns true when I send the data. The gms versions in the manifest match, and I've tried setting up the intent filter in the manifest too.
Here's the code I've been using:
Phone Part:
package a.package.name; //I've changed this here, to hide stuff.. it's the same as below, though.
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.Result;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.wearable.Asset;
import com.google.android.gms.wearable.DataApi;
import com.google.android.gms.wearable.DataEvent;
import com.google.android.gms.wearable.DataEventBuffer;
import com.google.android.gms.wearable.DataMap;
import com.google.android.gms.wearable.DataMapItem;
import com.google.android.gms.wearable.PutDataMapRequest;
import com.google.android.gms.wearable.PutDataRequest;
import com.google.android.gms.wearable.Wearable;
public class WatchCommsPhone implements DataApi.DataListener, GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, ResultCallback {
public static final String DATA_PATH_WATCH = "/watch_comms1";
public static final String DATA_PATH_PHONE = "/watch_comms2";
private GoogleApiClient gac;
Context c;
WatchCommsCallback wcc;
Handler h = new Handler();
public WatchCommsPhone(Context currentContext, WatchCommsCallback callback){
wcc = callback;
c = currentContext;
gac = new GoogleApiClient.Builder(c).addApi(Wearable.API).addConnectionCallbacks(this).addOnConnectionFailedListener(this).build();
gac.connect();
}
public void sendString(String message,long timestamp, String tag){
PutDataMapRequest pdmr = PutDataMapRequest.create(DATA_PATH_PHONE);
DataMap dm = pdmr.getDataMap();
Asset a = Asset.createFromBytes(message.getBytes());
dm.putAsset("data",a);
dm.putLong("timestamp", timestamp);
dm.putString("tag",tag);
PutDataRequest pdr = pdmr.asPutDataRequest();
pdr.setUrgent();
Wearable.DataApi.putDataItem(gac,pdr).setResultCallback(this);
}
#Override
public void onConnected(#Nullable Bundle bundle) {
Log.d("WatchCommsPhone","Watch Comms Watch: Connected");
Wearable.DataApi.addListener(gac,this);
}
#Override
public void onConnectionSuspended(int i) {
Log.d("WatchCommsPhone","Watch Comms Watch: Connection Suspended");
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.e("WatchCommsPhone","Watch Comms Watch: Connection Failed");
}
#Override
public void onDataChanged(DataEventBuffer dataEventBuffer) { //This gets called when you get data!
Log.d("WatchCommsPhone", "On Data Changed!");
for (DataEvent event: dataEventBuffer){
if (event.getType() == DataEvent.TYPE_CHANGED){
Log.d("WatchCommsPhone","Got data of path: " + event.getDataItem().getUri().getPath());
if(event.getDataItem().getUri().getPath().equals(DATA_PATH_WATCH)){
Log.d("WatchCommsPhone","Got data from watch.");
DataMap dm = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
String tag = dm.getString("tag");
Long timestamp = dm.getLong("timestamp");
String data = dm.getString("data");
ProcessData pd = new ProcessData(tag,data,timestamp);
h.post(pd);
}
}
}
}
#Override
public void onResult(#NonNull Result result) {
Log.d("WatchCommsPhone","onResultCalled: " + result.getStatus().isSuccess());
}
public interface WatchCommsCallback{
void onWatchMessageReceived(String tag, String message, long timestamp);
}
public class ProcessData implements Runnable{
String tag;
String data;
Long timestamp;
public ProcessData(String receivedTag, String receivedData, Long receivedTimestamp){
tag = receivedTag;
data = receivedData;
timestamp = receivedTimestamp;
}
#Override
public void run(){
wcc.onWatchMessageReceived(tag,data,timestamp);
}
}
}
Then the Wear part:
package a.package.name; //I've changed this here, to hide stuff.. it's the same as above, though.
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.Result;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.wearable.Asset;
import com.google.android.gms.wearable.DataApi;
import com.google.android.gms.wearable.DataEvent;
import com.google.android.gms.wearable.DataEventBuffer;
import com.google.android.gms.wearable.DataMap;
import com.google.android.gms.wearable.DataMapItem;
import com.google.android.gms.wearable.PutDataMapRequest;
import com.google.android.gms.wearable.PutDataRequest;
import com.google.android.gms.wearable.Wearable;
public class WatchCommsWatch implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, DataApi.DataListener, ResultCallback {
public static final String DATA_PATH_WATCH = "/watch_comms1";
public static final String DATA_PATH_PHONE = "/watch_comms2";
Context c;
GoogleApiClient gac;
WatchCommsCallback wcc;
Handler h = new Handler();
public WatchCommsWatch(Context currentContext,WatchCommsCallback callback){
wcc = callback;
c = currentContext;
gac = new GoogleApiClient.Builder(c).addApi(Wearable.API).addConnectionCallbacks(this).addOnConnectionFailedListener(this).build();
gac.connect();
}
public void sendString(String message,long timestamp, String tag){
PutDataMapRequest pdmr = PutDataMapRequest.create(DATA_PATH_WATCH);
pdmr.setUrgent();
DataMap dm = pdmr.getDataMap();
Asset a = Asset.createFromBytes(message.getBytes());
dm.putAsset("data",a);
dm.putLong("timestamp", timestamp);
dm.putString("tag",tag);
PutDataRequest pdr = pdmr.asPutDataRequest();
pdr.setUrgent();
Wearable.DataApi.putDataItem(gac,pdr).setResultCallback(this);
}
#Override
public void onConnected(#Nullable Bundle bundle) {
Log.d("WatchCommsWatch","Watch Connected.");
Wearable.DataApi.addListener(gac,this);
}
#Override
public void onConnectionSuspended(int i) {
Log.d("WatchCommsWatch","Watch Connection Suspended.");
}
#Override
public void onDataChanged(DataEventBuffer dataEventBuffer) {
Log.d("WatchCommsWatch","onDataChanged Called.");
for (DataEvent event: dataEventBuffer){
if (event.getType() == DataEvent.TYPE_CHANGED){
if(event.getDataItem().getUri().getPath().equals(DATA_PATH_WATCH)){
Log.d("WatchCommsWatch","Got data from watch.");
DataMap dm = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
String tag = dm.getString("tag");
Long timestamp = dm.getLong("timestamp");
Asset dataAsset = dm.getAsset("data");
//String data = new String(dataAsset.getData());
String data = tag;
ProcessData pd = new ProcessData(tag,data,timestamp);
h.post(pd);
}
}
}
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.e("WatchCommsWatch","WatchCommsWatch: Connection Failed.");
}
#Override
public void onResult(#NonNull Result result) {
Log.d("WatchCommsWatch","onResultCalled: " + result.getStatus().isSuccess());
}
public interface WatchCommsCallback{
void onWatchMessageReceived(String message, String tag, long timestamp);
}
public class ProcessData implements Runnable{
String tag;
String data;
Long timestamp;
public ProcessData(String receivedTag, String receivedData, Long receivedTimestamp){
tag = receivedTag;
data = receivedData;
timestamp = receivedTimestamp;
}
#Override
public void run(){
wcc.onWatchMessageReceived(tag,data,timestamp);
}
}
}
Thanks!
Of course you are free to choose their own way, but for my taste i prefer RXWear from Patloev
https://github.com/patloew/RxWear
See this snippet from my E52 watchface
Receive complex obj data from wear:
rxWear.message().listen("/dataMap", MessageApi.FILTER_LITERAL)
.compose(MessageEventGetDataMap.noFilter())
.subscribe(dataMap -> {
// String title = dataMap.getString("title", getString(R.string.no_message));
if (dataMap.containsKey("alWearTimersCategories")) {
String json = dataMap.getString("alWearTimersCategories");
alTimersCategories= allData.convertStringToALTimerWorkspace(json);
allData.setAlTimersCategoriesFromWear(alTimersCategories);
if (indata != null) {
timerdataset.refreshInternalData(alTimersCategories.get( iActiveWorkSpaceindex).alTimersCategoryInWorkspace);
}
}
});
Send some to clock:
rxWear.message().sendDataMapToAllRemoteNodes("/dataMap")
.putString("timers", "TimersCategories")
.putString("alTimersCategories", convertALTimerWorkspace(alTimersCategories))
.toObservable()
.subscribe(requestId -> { });
}

Unable to get output from Pd library and Android app

I am trying to get a simple Android app working with the Pd library I have integrated within my eclipse environment.
I have successfully build and compiled an example project called "CircleOfFifths" which proves that the library has been integrated fine in eclipse.
I am using cordova/phonegap and trying to create a plugin for libpd. All the plugin communication with the javascript file on the front-end is working fine.
The code seems to initialise and load the patch fine. It also goes into the play() method but I don't get any output. I am expecting to hear the sine wave.
I followed this tutorial on YouTube.
My code can be viewed here, and the patch is here.
Can anyone help me figure out where I can be going wrong?
My ultimate objective is to use a live audio from microphone and process that audio and return immediately with applied Pd patch (patch is ready and created for this) but before I go to that stage I want to make sure that I get some sort of output from the existing patch. Same patch as the one above in the YouTube tutorial.
package com.test.libpd;
import java.io.File;
import java.io.IOException;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaWebView;
import org.json.JSONArray;
import org.json.JSONException;
import org.puredata.android.io.AudioParameters;
import org.puredata.android.io.PdAudio;
import org.puredata.android.utils.PdUiDispatcher;
import org.puredata.core.PdBase;
import org.puredata.core.utils.IoUtils;
import android.content.Context;
import android.util.Log;
import com.sgil.libpddemo.R;
public class Libpd extends CordovaPlugin {
private static final String TAG = "libpd_plugin";
private Exception exception;
private Context AppContext;
private PdUiDispatcher dispatcher;
private static final int MIN_SAMPLE_RATE = 44100;
public Libpd() { // constructor
}
private Context getApplicationContext() {
return this.cordova.getActivity().getApplicationContext();
}
public void initialize(CordovaInterface cordova, CordovaWebView webView) {
super.initialize(cordova, webView);
Log.v(TAG, "Init LIBPD PLUGIN");
}
public boolean execute(final String action, final JSONArray args,
final CallbackContext callbackContext) throws JSONException {
cordova.getActivity().runOnUiThread(new Runnable() {
// #SuppressLint("NewApi")
public void run() {
Log.v(TAG, "Plugin received:" + action);
Libpd libpd = new Libpd();
libpd.AppContext = getApplicationContext();
try {
libpd.initPd(libpd.AppContext);
libpd.loadPatch(libpd.AppContext);
} catch (IOException e) {
Log.e(TAG, e.toString());
// libpd.finish();
}
if (action.equals("playRec")) {
// MediaRecordMethod mediaRecordMethod = new
// MediaRecordMethod(action);
// mediaRecordMethod.init();
libpd.play();
}
if (action.equals("stopRec")) {
libpd.onPause();
}
if (action.equals("startRec")) {
libpd.record("start");
libpd.play();
}
}
});
return true;
}
private void initPd(Context ctx) throws IOException {
AudioParameters.init(ctx);
// Configure the audio glue
int sampleRate = AudioParameters.suggestSampleRate();
int srate = Math.max(MIN_SAMPLE_RATE, AudioParameters.suggestSampleRate());
// int sampleRate = 64;
int inpch = AudioParameters.suggestInputChannels();
int outpch = AudioParameters.suggestOutputChannels();
PdAudio.initAudio(srate, 0, outpch, 8, true);
// Create and install the dispatcher
dispatcher = new PdUiDispatcher();
PdBase.setReceiver(dispatcher);
}
private void loadPatch(Context ctx) throws IOException {
File dir = ctx.getFilesDir();
Log.v(TAG, "path:" + dir.getAbsolutePath().toString());
//File dir = new File("/sdcard/mypatches");
IoUtils.extractZipResource(
ctx.getResources().openRawResource(R.raw.simplepatch), dir, true);
File patchFile = new File(dir, "simplepatch.pd");
PdBase.openPatch(patchFile.getAbsolutePath());
//PdAudio.startAudio(ctx);
//this.record("start");
}
private void record(String startorStop) {
if (startorStop.equals("start")) {
PdBase.sendSymbol("recordfilename", "x.aiff");
PdBase.sendBang("openfile");
PdBase.sendBang("record");
} else {
PdBase.sendBang("stoprecording");
}
}
// play back the last recording from the file called 'recorded'
public void play() {
//PdBase.sendSymbol("playfilename", "x.aiff");
//PdBase.sendBang("readfile");
//PdBase.sendBang("play");
Float val = 1.0f;
PdBase.sendFloat("onOff", val);
}
protected void onPause() {
PdAudio.stopAudio();
PdAudio.release();
PdBase.release();
}
}
your code never starts the audio-processing.
For whatever reasons youhave uncommented the line
PdAudio.startAudio(ctx)

webserver for file upload on android

I would like to add a webserver to my android application for uploading small files to the phone.
The user would start the webserver from the phone by hitting a button. He would then see an ip address that can be accessed by any browser from a pc. The website behind this ip address should show a file upload opportunity.
My question is: Is there an open source project similar to my needs? Or how would you recommend doing this?
you can use NanoHttpd link it's very weight android web server that is nicely embbedible..
package .....;
import java.io.IOException;
import java.util.Map.Entry;
import java.util.Properties;
import android.app.Activity;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Handler;
import android.widget.TextView;
public class AndroidWebServerActivity extends Activity {
private static final int PORT = 8765;
private TextView hello;
private MyHTTPD server;
private Handler handler = new Handler();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
#Override
protected void onResume() {
super.onResume();
try {
server = new MyHTTPD();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
protected void onPause() {
super.onPause();
if (server != null)
server.stop();
}
private class MyHTTPD extends NanoHTTPD {
public MyHTTPD() throws IOException {
super(PORT, null);
}
#Override
public Response serve(String uri, String method, Properties header, Properties parms, Properties files) {
final StringBuilder buf = new StringBuilder();
for (Entry<Object, Object> kv : header.entrySet())
buf.append(kv.getKey() + " : " + kv.getValue() + "\n");
handler.post(new Runnable() {
#Override
public void run() {
}
});
final String html = "<html><head><head><body><h1>Hello, World</h1></body></html>";
return new NanoHTTPD.Response(HTTP_OK, MIME_HTML, html);
}
}
}

no communication between pub/sub code in android using zeromq

I tried to implement a simple publisher and subscriber in android using zeromq. When i try to debug it loops in subscriber recv. I dont know where i am going wrong. I think it is not able to get any data from the publisher.
Below is the code :subscriber
package com.example.jeromqps;
import java.util.*;
import org.jeromq.ZMQ;
import android.os.AsyncTask;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
public class client implements Runnable {
Messenger messenger;
public client()
{
System.out.println("client started");
}
#Override
public void run()
{
ZMQ.Context context=ZMQ.context(1);
System.out.println("collecting data from server");
ZMQ.Socket subscriber=context.socket(ZMQ.SUB);
subscriber.connect("tcp://localhost:4444");
String code="10001";
subscriber.subscribe(code.getBytes());
int totalvalue=0;
//store the data in a data structure
for(int i=0;i<10;i++)
{
byte[] msg = subscriber.recv(0);
String string=new String(subscriber.recv(0));
StringTokenizer sscanf=new StringTokenizer(string," ");
int value=Integer.valueOf(sscanf.nextToken());
String string= new String(msg);
System.out.println();
totalvalue+=value;
}
int avg=totalvalue;
Message msg1=Message.obtain();
msg1.obj=string;
try {
messenger.send(msg1);
System.out.println("sent to main");
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
subscriber.close();
context.term();
}
}
The publisher code is below
package com.example.jeromqps;
import java.util.*;
import org.jeromq.*;
public class server implements Runnable{
public server()
{
System.out.println("server started");
}
#Override
public void run()
{
ZMQ.Context context=ZMQ.context(1);
ZMQ.Socket publisher=context.socket(ZMQ.PUB);
publisher.bind("tcp://*:4444");
Random srandom=new Random(System.currentTimeMillis());
System.out.println("in server");
while(!Thread.currentThread().isInterrupted())
{ //System.out.println("in while")
int zipcode =1000 +srandom.nextInt(10000);
int temperature = srandom.nextInt(215) - 80 + 1;
String update = String.format("%05d %d", zipcode, temperature);
String update="publisher";
publisher.send(update.getBytes(),0);
}
publisher.close();
context.term();
}
}
Main is below:
package com.example.jeromqps;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.app.Activity;
import android.app.AlertDialog;
import android.os.Bundle;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.os.Handler;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MainActivity extends Activity implements Handler.Callback {
private TextView textView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new server()).start();
new Thread(new client()).start();
}
#Override
public boolean handleMessage(Message arg0)
{
String str = new String((byte[]) arg0.obj);
System.out.println("****");
System.out.println(str);
//new AlertDialog.Builder(this).setMessage(str).show();
System.out.println("****");
textView.append(str+ "\n");
return false;
}
}
In program loops at byte[] msg = subscriber.recv(0); in the subscribers class. Where am i going wrong?Am i missing something?
First of all, you've got some errors in the code:
In the publisher, update is defined twice
String update = String.format("%05d %d", zipcode, temperature);
String update= "publisher";
You have a similar problem in the subscriber code, string is defined twice...
String string = new String(subscriber.recv(0));
String string = new String(msg);
In the subscriber, you're receiving messages twice in the same iteration..
byte[] msg = subscriber.recv(0);
String string = new String(subscriber.recv(0));
...you only need this in the loop to receive...
String string = new String(subscriber.recv(0));
Try fixing those problems and see how far you get...
This isn't a solution to the question posted here, but reading this question I noticed that 0 was specified as the second parameter in the send(...) method, which subsequently matches the parameter set in the recv(...) method.
I have a simple pub/sub system set up and couldn't figure out why messages weren't being sent. I was using recv(0) but was specifying some random flag in the send(...) method. Changing the value to 0 fixed my issues.
Figured I'd post this here as it was from reading through the code in the question that I happened to have that thought. So maybe this will help someone else in the future.

Android: Force close when reading from Socket

I'm trying to make a client in Android. This clients runs a thread that creates the client socket and launches another thread that is always listening to the socket to receive Strings. Everything is OK when I send a String from the client to a Java server running in a PC, but when I send a String from the server to the Android client the app finishes. Why do I get this error?
Here is the code of the main Activity of the client:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends Activity {
TextView chatHistorial;
EditText msg;
Socket client;
DataInputStream in;
DataOutputStream out;
Boolean cerrar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Thread t = new Thread(new Runnable(){
#Override
public void run() {
try{
client = new Socket("192.168.1.33", 4444);
in = new DataInputStream(client.getInputStream());
out = new DataOutputStream(client.getOutputStream());
cerrar = false;
chatHistorial = (TextView) findViewById(R.id.chatHistorial);
msg = (EditText) findViewById(R.id.msg);
ThreadLectura tl = new ThreadLectura(in, cerrar, chatHistorial);
tl.start();
}
catch(Exception e){
// ...
}
}
});
t.start();
findViewById(R.id.enviar).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String cadena = msg.getText().toString();
try {
out.writeUTF(cadena);
} catch (IOException e) {
// ...
}
if(cadena.equals("exit"))
cerrar = true;
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
//getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
class ThreadLectura extends Thread{
DataInputStream in;
String cadena;
TextView chatHistorial;
Boolean cerrar;
public ThreadLectura(DataInputStream in, Boolean cerrar, TextView tv){
this.in = in;
this.cerrar = cerrar;
chatHistorial = tv;
}
#Override
public void run(){
try{
while(!cerrar){
cadena = in.readUTF();
chatHistorial.append("Has recibido: " + cadena);
}
}
catch(IOException ioe){
System.out.println("Error de entrada/salida: "+ioe.getMessage());
}
}
}
It's hard to say without seeing your logcat output, but I'm betting it's because you are attempting to modify the UI from within your background thread. This line within ThreadLectura:
chatHistorial.append("Has recibido: " + cadena);
is probably the issue, as chatHistorial is a TextView. You need to only modify the UI from within the main UI thread.

Categories

Resources