I am an novice android developer, I am using MQTT protocol for my android app.
I have found a code from internet for MQTT.But problem is that i have to use this MQTT Code for every activity which is redundant.I want to make a common java class
which can be call called any time whenever i need MQTT connection and communication.I have already tried but failed.Please anyone suggest me how to approach this?The code is given below
com.example.ab.mushroomv2;
import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
public class DashboardActivity extends AppCompatActivity {
final Context context = this;
//private EditText result;
private static final String TAG = "DA";
ProgressBar p_temp;
TextView progressingTemp;
MqttAndroidClient client;
String clientId;
static String topicTemp = "mushroom/temp";
String subMsg, top;
static String host = "tcp://iot.eclipse.org:1883";
Handler progressHandler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dashboard);
p_temp = (ProgressBar) findViewById(R.id.progress_bar_temp);
progressingTemp = (TextViewfindViewById(R.id.progress_circle_temp_text);
establish();
client.setCallback(new MqttCallback() {
#Override
public void connectionLost(Throwable cause) {
establish();
}
#Override
public void messageArrived(String topic, MqttMessage message) throws
Exception {
subMsg = new String(message.getPayload());
top=new String(topic);
if(top.contains("temp"))
{
double a=Double.parseDouble(subMsg);
final int msgTemp = (int) a;
Log.d(TAG, String.valueOf(msgTemp));
new Thread(new Runnable() {
public void run() {
progressHandler.post(new Runnable() {
public void run() {
p_temp.setProgress(msgTemp);
progressingTemp.setText("" + msgTemp + " ℃
");
}
});
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
#Override
public void deliveryComplete(IMqttDeliveryToken token) {
}
});
}
public void establish() {
clientId = MqttClient.generateClientId();
client = new MqttAndroidClient(this.getApplicationContext(), host,
clientId);
try {
IMqttToken token = client.connect();
token.setActionCallback(new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
// We are connected
Toast.makeText(DashboardActivity.this, "Client Connected",
Toast.LENGTH_SHORT).show();
try {
client.subscribe(topicTemp, 0);
} catch (MqttException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable
exception) {
Toast.makeText(DashboardActivity.this, "Client failed to
Connect", Toast.LENGTH_SHORT).show();
// establish();
}
});
} catch (MqttException e) {
e.printStackTrace();
}
}
}
You need to create a singleton class. Here is an sample.
public class SocketIO {
private static final String TAG = SocketIO.class.getSimpleName();
private static SocketIO instance;
private Socket socket;
private SocketIO() {
try {
socket = IO.socket("http://ur_url_here");
} catch (URISyntaxException e) {
e.printStackTrace();
Log.e(TAG, e.getMessage());
}
}
public static synchronized SocketIO getInstance() {
if (instance == null) {
instance = new SocketIO();
}
return instance;
}
public Socket getSocket() {
return socket;
}
public void open() {
if (socket != null)
socket.open();
}
public void close() {
if (socket != null)
socket.close();
}}
Related
I have MyRepository that obtains a live feed from a server via a socket.
It provides its data to MyViewModel via a MutableLiveData object which can be observed from a Fragment.
To avoid wasting resources, I don't want MyRepository to be obtaining data from the server when there are no observers.
I'd like to know how to monitor MyRepository's MutableLiveData, so if there are no observers then MyRepository can stop retrieving data from the server. Similarly, if an observer is added, then data retrieval can (re)start.
Currently, I'm just using a basic Thread (see the createObserversMonitorThread() method) as the monitor:
public class MyRepository {
private static final String TAG = MyRepository.class.getSimpleName();
private MutableLiveData<String> mutableLiveData;
private Socket mSocket = null;
public MyRepository(Application application) {
mutableLiveData = new MutableLiveData<>();
createSocket();
createObserversMonitorThread();
}
private void createObserversMonitorThread() {
Thread thread = new Thread() {
#Override
public void run() {
try {
while (isAlive()) {
if (mutableLiveData.hasActiveObservers()) {
// We have observers, so connect to the server.
if (!mSocket.connected()) {
mSocket.connect();
}
}
else {
// We don't have observers, so disconnect from the server.
if (mSocket.connected()) {
mSocket.disconnect();
}
}
// Wait until next loop.
Thread.sleep(1000);
}
}
catch(Exception e) {
Log.e(TAG, "Exception", e);
}
}
};
thread.setName("MutableLiveData Observers Monitor");
thread.setPriority(1);
thread.setDaemon(true);
thread.start();
}
public LiveData<String> getMutableLiveData() {
return mutableLiveData;
}
/**
* This method posts retrieved data to mutableLiveData.
*/
private void createSocket() {
try {
mSocket = IO.socket(Constants.SERVER_URL);
mSocket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.d(TAG, "Connected.");
}
}).on(Socket.EVENT_CONNECT_ERROR, new Emitter.Listener() {
#Override
public void call(Object... args) {
if (args[0] instanceof Exception) {
Log.e(TAG, "Connect error: ", (Exception)args[0]);
}
else {
Log.e(TAG, "Connect error: " + args[0]);
}
}
}).on(Socket.EVENT_RECONNECT, new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.d(TAG, "Reconnected.");
}
}).on(Socket.EVENT_RECONNECT_ERROR, new Emitter.Listener() {
#Override
public void call(Object... args) {
if (args[0] instanceof Exception) {
Log.e(TAG, "Reconnect error: ", (Exception)args[0]);
}
else {
Log.e(TAG, "Reconnect error: " + args[0]);
}
}
}).on(Socket.EVENT_MESSAGE, new Emitter.Listener() {
#Override
public void call(Object... args) {
//Log.d(TAG, "Data received.");
String s = (String) args[0];
mutableLiveData.postValue(s);
}
}).on(Socket.EVENT_DISCONNECT, new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.d(TAG, "Disconnected.");
}
}).on(Socket.EVENT_ERROR, new Emitter.Listener() {
#Override
public void call(Object... args) {
if (args[0] instanceof Exception) {
Log.e(TAG, "Error: ", (Exception)args[0]);
}
else {
Log.e(TAG, "Error: " + args[0]);
}
}
});
}
catch(Exception e) {
Log.e(TAG, "Could not create socket", e);
}
}
}
It works, but is there a better way?
UPDATE
Solution, thanks to EpicPandaForce's answer:
public class MyRepository {
private static final String TAG = MyRepository.class.getSimpleName();
private MutableLiveData<String> mutableLiveData;
private Socket mSocket = null;
public MyRepository(Application application) {
createSocket();
mutableLiveData = new MutableLiveData<String>() {
#Override
protected void onActive() {
super.onActive();
// Connect to server. This will (re)start data being posted on mutableLiveData.
if (!mSocket.connected()) {
mSocket.connect();
}
}
#Override
protected void onInactive() {
super.onInactive();
// Disconnect from server. This will stop data being posted on mutableLiveData.
if (mSocket.connected()) {
mSocket.disconnect();
}
}
};
}
public LiveData<String> getMutableLiveData() {
return mutableLiveData;
}
/**
* This method posts retrieved data to mutableLiveData.
*/
private void createSocket() {
// Same code as before.
}
}
You can use extends LiveData<T> or extends MutableLiveData<T> to get ahold of onActive() callback where you are notified if you have at least 1 active observer, and onInactive() callback when you went from 1 to 0 active observers.
That way you don't even need to ask for hasActiveObservers().
I am trying to create a Chat Application using WiFip2p.Everything is done in this application. Before send and receive message app was working good. After that, I got this error. I am getting this error when I connect to another device. It shows a null object reference. I don't know why I need a solution can anyone help me thank you.
public class WiFi_Activity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_wi_fi_);
FINDVIEWBYID();
CLICKLISTINER();
}
Handler handler=new Handler(new Handler.Callback() {
#Override
public boolean handleMessage(Message msg) {
switch (msg.what)
{
case MESSAGE_READ:
byte[] readbuffer=(byte[])msg.obj;
String tempmez=new String(readbuffer,0,msg.arg1);
txt_message.setText(tempmez);
break;
}
return true;
}
});
private void FINDVIEWBYID() {
btn_onoff=findViewById(R.id.onOff);
btn_discover=findViewById(R.id.discover);
btn_send=findViewById(R.id.sendButton);
listView=findViewById(R.id.peerListView);
txt_connectionsts=findViewById(R.id.connectionStatus);
txt_message=findViewById(R.id.readMsg);
edit_message=findViewById(R.id.writeMsg);
wifiManager= (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
wifiP2pManager= (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
channel=wifiP2pManager.initialize(this,getMainLooper(),null);
broadcastReceiver=new Wifi_broadcast_reciever(wifiP2pManager,channel,this);
intentFilter=new IntentFilter();
intentFilter.addAction(wifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
intentFilter.addAction(wifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
intentFilter.addAction(wifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
intentFilter.addAction(wifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
}
private void CLICKLISTINER() {
btn_onoff.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (wifiManager.isWifiEnabled())
{
wifiManager.setWifiEnabled(false);
btn_onoff.setText("ON");
}
else
{
wifiManager.setWifiEnabled(true);
btn_onoff.setText("OFF");
}
}
});
btn_discover.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
wifiP2pManager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
txt_connectionsts.setText("Discovery Started");
}
#Override
public void onFailure(int reason) {
txt_connectionsts.setText("Discovery starting failuree"+String.valueOf(reason));
}
});
}
});
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final WifiP2pDevice wifiP2pDevice=devicearray[position];
WifiP2pConfig config=new WifiP2pConfig();
config.deviceAddress=wifiP2pDevice.deviceAddress;
wifiP2pManager.connect(channel, config, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
Toast.makeText(WiFi_Activity.this, "Connect with"+ wifiP2pDevice.deviceName, Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(int reason) {
Toast.makeText(WiFi_Activity.this, "Not connected", Toast.LENGTH_SHORT).show();
}
});
}
});
btn_send.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String msz=edit_message.getText().toString();
sendRecieve.write(msz.getBytes());
}
});
}
WifiP2pManager.PeerListListener peerListListener=new WifiP2pManager.PeerListListener() {
#Override
public void onPeersAvailable(WifiP2pDeviceList peerslist) {
if (!peerslist.getDeviceList().equals(peers));
{
peers.clear();
peers.addAll(peerslist.getDeviceList());
devicename_array=new String[peerslist.getDeviceList().size()];
devicearray=new WifiP2pDevice[peerslist.getDeviceList().size()];
int index= 0;
for (WifiP2pDevice device:peerslist.getDeviceList())
{
devicename_array[index]=device.deviceName;
devicearray[index]=device;
index++;
}
ArrayAdapter<String> arrayAdapter=new ArrayAdapter<String>(getApplicationContext(),R.layout.support_simple_spinner_dropdown_item,devicename_array);
listView.setAdapter(arrayAdapter);
}
if (peers.size()==0)
{
Toast.makeText(WiFi_Activity.this, "No discover show", Toast.LENGTH_SHORT).show();
}
}
};
WifiP2pManager.ConnectionInfoListener connectionInfoListener=new WifiP2pManager.ConnectionInfoListener() {
#Override
public void onConnectionInfoAvailable(WifiP2pInfo info) {
final InetAddress owneraddress= info.groupOwnerAddress;
if (info.groupFormed && info.isGroupOwner)
{
txt_connectionsts.setText("Host");
serverclass=new Serverclass();
serverclass.start();
}
else if (info.groupFormed)
{
txt_connectionsts.setText("Client");
clientclass = new Clientclass(owneraddress);
clientclass.start();
}
}
};
#Override
protected void onResume() {
super.onResume();
registerReceiver(broadcastReceiver,intentFilter);
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(broadcastReceiver);
}
public class Serverclass extends Thread
{
Socket socket;
ServerSocket serverSocket;
#Override
public void run() {
try {
serverSocket=new ServerSocket(1111);
socket=serverSocket.accept();
sendRecieve=new SendRecieve(socket);
sendRecieve.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class Clientclass extends Thread
{
Socket socket;
String host_address;
public Clientclass(InetAddress hostaddress){
host_address=hostaddress.getHostAddress();
socket=new Socket();
sendRecieve=new SendRecieve(socket);
sendRecieve.start();
}
#Override
public void run() {
try {
socket.connect(new InetSocketAddress(host_address,1111),500);
} catch (IOException e) {
e.printStackTrace();
}
}
}
private class SendRecieve extends Thread
{
private Socket socket;
private InputStream inputStream;
private OutputStream outputStream;
public SendRecieve(Socket skt)
{
socket=skt;
try {
inputStream=socket.getInputStream();
outputStream=socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void run() {
byte[] buffer=new byte[2048];
int bytes;
while (socket!=null)
{
try {
bytes=inputStream.read(buffer);
if (bytes>0)
{
handler.obtainMessage(MESSAGE_READ,bytes,-1,buffer).sendToTarget();
}
} catch (IOException e) {
Log.d("error",e.getMessage());
}
}
}
public void write(byte[] bytes)
{
try {
outputStream.write(bytes);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
I am getting this error on this part of code:-
#Override
public void run() {
byte[] buffer=new byte[2048];
int bytes;
while (socket!=null)
{
try {
bytes=inputStream.read(buffer);
if (bytes>0)
{
handler.obtainMessage(MESSAGE_READ,bytes,-1,buffer).sendToTarget();
}
} catch (IOException e) {
Log.d("error",e.getMessage());
}
}
}
The only thing I can see as being an issue is that you're catching (and ignoring) errors from getInputStream() and getOutputStream(). The exception is stopping execution, so if getInputStream() errors out, it doesn't get set. Both of your streams would be null.
Since you're at least printing the stacktrace, check for other stacktraces before the actual crash. It may tell you more about what went wrong.
To get around this, I suggest not catching the exception and instead making the constructor throw IOException. If you catch it early, it will cause less problems for you later on.
Edit: I've looked at your classes a bit more, and I see that you don't set the address of the Socket in time. Do that before you get the data streams for it. Not using the fields will work.
private Socket socket;
public SendRecieve(Socket skt) {
this.socket = skt;
}
#Override
public void run() {
try {
InputStream in = socket.getInputStream();
... etc
} ...
}
You calling Sendreceiver start before Clientclas run executes, so the following is necessary:
public class Clientclass extends Thread {
Socket socket;
String host_address;
public Clientclass(InetAddress hostaddress){
host_address=hostaddress.getHostAddress();
socket=new Socket();
}
#Override
public void run() {
try {
socket.connect(new InetSocketAddress(host_address,1111),500);
sendRecieve=new SendRecieve(socket);
sendRecieve.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I am using Network Service Discovery service to discovery peer and connected to them using socket so , so socket created successfully but i am not able to send message or receive message so below is my code
MainActivity
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private NSDHelper mNsdHelper;
private int port;
private Context mContext;
ChatConnection mConnection;
private Button mDiscover, advertise_btn, connect_btn;
private Handler mUpdateHandler;
private TextView mStatusView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mStatusView = (TextView) findViewById(R.id.status);
mContext = MainActivity.this;
mUpdateHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
String chatLine = msg.getData().getString("msg");
addChatLine(chatLine);
}
};
mConnection = new ChatConnection(mUpdateHandler);
mNsdHelper = new NSDHelper(this);
mNsdHelper.initNSD();
advertise_btn = (Button) findViewById(R.id.advertise_btn);
connect_btn = (Button) findViewById(R.id.connect_btn);
advertise_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Register service
if (mConnection.getLocalPort() > -1) {
mNsdHelper.registerService(mConnection.getLocalPort());
} else {
Log.d(TAG, "ServerSocket isn't bound.");
}
}
});
connect_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
NsdServiceInfo service = mNsdHelper.getChosenServiceInfo();
if (service != null) {
Log.d(TAG, "Connecting.");
mConnection.connectToServer(service.getHost(),
service.getPort());
} else {
Log.d(TAG, "No service to connect to!");
}
}
});
mDiscover = (Button) findViewById(R.id.discover_btn);
mDiscover.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mNsdHelper.discoverServices();
}
});
}
public void clickSend(View v) {
EditText messageView = (EditText) this.findViewById(R.id.chatInput);
if (messageView != null) {
String messageString = messageView.getText().toString();
if (!messageString.isEmpty()) {
mConnection.sendMessage(messageString);
}
messageView.setText("");
}
}
public void addChatLine(String line) {
mStatusView.append("\n" + line);
}
#Override
protected void onPause() {
if (mNsdHelper != null) {
mNsdHelper.stopDiscovery();
}
super.onPause();
}
#Override
protected void onResume() {
super.onResume();
if (mNsdHelper != null) {
mNsdHelper.discoverServices();
}
}
#Override
protected void onDestroy() {
mNsdHelper.tearDown();
mConnection.tearDown();
super.onDestroy();
}
}
ChatConnection
public class ChatConnection {
private Handler mUpdateHandler;
private ChatServer mChatServer;
private ChatClient mChatClient;
private static final String TAG = "ChatConnection";
private Socket mSocket;
private int mPort = -1;
public ChatConnection(Handler handler) {
mUpdateHandler = handler;
mChatServer = new ChatServer(handler);
}
public void tearDown() {
mChatServer.tearDown();
mChatClient.tearDown();
}
public void connectToServer(InetAddress address, int port) {
mChatClient = new ChatClient(address, port);
}
public void sendMessage(String msg) {
if (mChatClient != null) {
mChatClient.sendMessage(msg);
}
}
public int getLocalPort() {
return mPort;
}
public void setLocalPort(int port) {
mPort = port;
}
public synchronized void updateMessages(String msg, boolean local) {
Log.e(TAG, "Updating message: " + msg);
if (local) {
msg = "me: " + msg;
} else {
msg = "them: " + msg;
}
Bundle messageBundle = new Bundle();
messageBundle.putString("msg", msg);
Message message = new Message();
message.setData(messageBundle);
mUpdateHandler.sendMessage(message);
}
private synchronized void setSocket(Socket socket) {
Log.d(TAG, "setSocket being called.");
if (socket == null) {
Log.d(TAG, "Setting a null socket.");
}
if (mSocket != null) {
if (mSocket.isConnected()) {
try {
mSocket.close();
} catch (IOException e) {
// TODO(alexlucas): Auto-generated catch block
e.printStackTrace();
}
}
}
mSocket = socket;
}
private Socket getSocket() {
return mSocket;
}
private class ChatServer {
ServerSocket mServerSocket = null;
Thread mThread = null;
public ChatServer(Handler handler) {
mThread = new Thread(new ServerThread());
mThread.start();
}
public void tearDown() {
mThread.interrupt();
try {
mServerSocket.close();
} catch (IOException ioe) {
Log.e(TAG, "Error when closing server socket.");
}
}
class ServerThread implements Runnable {
#Override
public void run() {
try {
// Since discovery will happen via Nsd, we don't need to care which port is
// used. Just grab an available one and advertise it via Nsd.
mServerSocket = new ServerSocket(0);
setLocalPort(mServerSocket.getLocalPort());
while (!Thread.currentThread().isInterrupted()) {
Log.d(TAG, "ServerSocket Created, awaiting connection");
setSocket(mServerSocket.accept());
Log.d(TAG, "Connected.");
if (mChatClient == null) {
int port = mSocket.getPort();
InetAddress address = mSocket.getInetAddress();
connectToServer(address, port);
}
}
} catch (IOException e) {
Log.e(TAG, "Error creating ServerSocket: ", e);
e.printStackTrace();
}
}
}
}
private class ChatClient {
private InetAddress mAddress;
private int PORT;
private final String CLIENT_TAG = "ChatClient";
private Thread mSendThread;
private Thread mRecThread;
public ChatClient(InetAddress address, int port) {
Log.d(CLIENT_TAG, "Creating chatClient");
this.mAddress = address;
this.PORT = port;
mSendThread = new Thread(new SendingThread());
mSendThread.start();
}
class SendingThread implements Runnable {
BlockingQueue<String> mMessageQueue;
private int QUEUE_CAPACITY = 10;
public SendingThread() {
mMessageQueue = new ArrayBlockingQueue<String>(QUEUE_CAPACITY);
}
#Override
public void run() {
try {
if (getSocket() == null) {
setSocket(new Socket(mAddress, PORT));
Log.d(CLIENT_TAG, "Client-side socket initialized.");
} else {
Log.d(CLIENT_TAG, "Socket already initialized. skipping!");
}
mRecThread = new Thread(new ReceivingThread());
mRecThread.start();
} catch (UnknownHostException e) {
Log.d(CLIENT_TAG, "Initializing socket failed, UHE", e);
} catch (IOException e) {
Log.d(CLIENT_TAG, "Initializing socket failed, IOE.", e);
}
while (true) {
try {
String msg = mMessageQueue.take();
sendMessage(msg);
} catch (InterruptedException ie) {
Log.d(CLIENT_TAG, "Message sending loop interrupted, exiting");
}
}
}
}
class ReceivingThread implements Runnable {
#Override
public void run() {
BufferedReader input;
try {
input = new BufferedReader(new InputStreamReader(
mSocket.getInputStream()));
while (!Thread.currentThread().isInterrupted()) {
String messageStr = null;
messageStr = input.readLine();
if (messageStr != null) {
Log.d(CLIENT_TAG, "Read from the stream: " + messageStr);
updateMessages(messageStr, false);
} else {
Log.d(CLIENT_TAG, "The nulls! The nulls!");
break;
}
}
input.close();
} catch (IOException e) {
Log.e(CLIENT_TAG, "Server loop error: ", e);
}
}
}
public void tearDown() {
try {
getSocket().close();
} catch (IOException ioe) {
Log.e(CLIENT_TAG, "Error when closing server socket.");
}
}
public void sendMessage(String msg) {
try {
Socket socket = getSocket();
if (socket == null) {
Log.d(CLIENT_TAG, "Socket is null, wtf?");
} else if (socket.getOutputStream() == null) {
Log.d(CLIENT_TAG, "Socket output stream is null, wtf?");
}
PrintWriter out = new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(getSocket().getOutputStream())), true);
out.println(msg);
out.flush();
updateMessages(msg, true);
} catch (UnknownHostException e) {
Log.d(CLIENT_TAG, "Unknown Host", e);
} catch (IOException e) {
Log.d(CLIENT_TAG, "I/O Exception", e);
} catch (Exception e) {
Log.d(CLIENT_TAG, "Error3", e);
}
Log.d(CLIENT_TAG, "Client sent message: " + msg);
}
}
}
NSDHelper
public class NSDHelper {
private static final String TAG = NSDHelper.class.getSimpleName();
NsdManager mNsdManager;
public static final String SERVICE_TYPE = "_geoStorm._tcp.";
public String mServiceName = "DROIDDEVICE";
NsdManager.DiscoveryListener mDiscoveryListener;
NsdManager.RegistrationListener mRegistrationListener;
NsdManager.ResolveListener mResolveListener;
NsdServiceInfo mService;
private Context mContext;
public NSDHelper(Context _context) {
mContext = _context;
mNsdManager = (NsdManager) mContext.getSystemService(Context.NSD_SERVICE);
}
public void initNSD() {
initializeResolveListener();
initializeDiscoveryListener();
initializeRegistrationListener();
}
/**
* This method is to register NSD
*
* #param port
*/
public void registerService(int port) {
NsdServiceInfo nsdServiceInfo = new NsdServiceInfo();
nsdServiceInfo.setPort(port);
nsdServiceInfo.setServiceName(mServiceName);
nsdServiceInfo.setServiceType(SERVICE_TYPE);
mNsdManager.registerService(nsdServiceInfo, NsdManager.PROTOCOL_DNS_SD,
mRegistrationListener);
}
public void initializeResolveListener() {
mResolveListener = new NsdManager.ResolveListener() {
#Override
public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
Log.e(TAG, "Resolve failed" + errorCode);
}
#Override
public void onServiceResolved(NsdServiceInfo serviceInfo) {
Log.e(TAG, "Resolve Succeeded. " + serviceInfo);
if (serviceInfo.getServiceName().equals(mServiceName)) {
Log.d(TAG, "Same IP.");
return;
}
mService = serviceInfo;
}
};
}
public void initializeDiscoveryListener() {
mDiscoveryListener = new NsdManager.DiscoveryListener() {
#Override
public void onStartDiscoveryFailed(String serviceType, int errorCode) {
Log.e(TAG, "Discovery failed: Error code:" + errorCode);
mNsdManager.stopServiceDiscovery(this);
}
#Override
public void onStopDiscoveryFailed(String serviceType, int errorCode) {
Log.e(TAG, "Discovery failed: Error code:" + errorCode);
mNsdManager.stopServiceDiscovery(this);
}
#Override
public void onDiscoveryStarted(String serviceType) {
Toast.makeText(mContext, "Discovery Started Successfully ",
Toast.LENGTH_LONG).show();
Log.d(TAG, "Service discovery started");
}
#Override
public void onDiscoveryStopped(String serviceType) {
Log.i(TAG, "Discovery stopped: " + serviceType);
Toast.makeText(mContext, "Discovery stopped", Toast.LENGTH_LONG).show();
}
#Override
public void onServiceFound(NsdServiceInfo serviceInfo) {
Log.d(TAG, "Service discovery success" + serviceInfo);
if (!serviceInfo.getServiceType().equals(SERVICE_TYPE)) {
Toast.makeText(mContext, "Unknown Service Type", Toast.LENGTH_LONG).show();
} else if (serviceInfo.getServiceName().equals(mServiceName)) {
Log.d(TAG, "Same machine: " + mServiceName);
} else if (serviceInfo.getServiceName().contains(mServiceName)) {
mNsdManager.resolveService(serviceInfo, mResolveListener);
}
Log.d(TAG, serviceInfo.getPort() + "");
// Log.d(TAG, new InetSocketAddress(serviceInfo.getHost());)
}
#Override
public void onServiceLost(NsdServiceInfo serviceInfo) {
Log.e(TAG, "service lost" + serviceInfo);
Toast.makeText(mContext, "service Lost" + serviceInfo, Toast.LENGTH_LONG).show();
if (mService == serviceInfo) {
mService = null;
}
}
};
}
public void initializeRegistrationListener() {
mRegistrationListener = new NsdManager.RegistrationListener() {
#Override
public void onRegistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
}
#Override
public void onUnregistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
}
#Override
public void onServiceRegistered(NsdServiceInfo serviceInfo) {
mServiceName = serviceInfo.getServiceName();
}
#Override
public void onServiceUnregistered(NsdServiceInfo serviceInfo) {
}
};
}
public void discoverServices() {
if (mNsdManager != null)
mNsdManager.discoverServices(
SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);
}
public void stopDiscovery() {
mNsdManager.stopServiceDiscovery(mDiscoveryListener);
}
public NsdServiceInfo getChosenServiceInfo() {
return mService;
}
public void tearDown() {
mNsdManager.unregisterService(mRegistrationListener);
mNsdManager.stopServiceDiscovery(mDiscoveryListener);
mNsdManager = null;
mRegistrationListener = null;
}
}
I need help in this that how i can send message using socket , coz i stuck i am not getting any nothing , any help would be appreciated.
MainActivity.java
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client();
try {
client.connect("192.168.1.10",5555);
} catch (IOException e) {
e.printStackTrace();
}
}
public void displayServerAnswer(String answer){
TextView textView = (TextView)findViewById(R.id.mainTextView);
textView.setText(answer);
}
...
Client.java
import java.net.Socket;
import java.io.PrintWriter;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Observable;
public class Client extends Observable implements Runnable {
private Socket socket;
private BufferedReader br;
private PrintWriter pw;
private boolean connected;
private int port=5555; //default port
private String hostName="localhost";//default host name
public Client() {
connected = false;
}
public void connect(String hostName, int port) throws IOException {
if(!connected)
{
this.hostName = hostName;
this.port = port;
socket = new Socket(hostName,port);
//get I/O from socket
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
pw = new PrintWriter(socket.getOutputStream(),true);
connected = true;
//initiate reading from server...
Thread t = new Thread(this);
t.start(); //will call run method of this class
}
}
public void sendMessage(String msg) throws IOException
{
if(connected) {
pw.println(msg);
} else throw new IOException("Not connected to server");
}
public void run() {
String msg = ""; //holds the msg recieved from server
try {
while(connected && (msg = br.readLine())!= null)
{
//In Here I want to call MainActivity.displayServerAnswer()
//notify observers//
this.setChanged();
//notify+send out recieved msg to Observers
this.notifyObservers(msg);
}
}
catch(IOException ioe) { }
finally { connected = false; }
}
...
}
In the place I specified, I want to be able to display the server answer.
How can I get access to MainActivity instance that created client object, in order to call its method?
#hopia answer is pretty good. you also can implement the Listener Design pattern
public class Client extends Observable implements Runnable {
public interface ClientListener {
public void onAction();
}
private ClientListener mListener;
public Client(ClientListener listener) {
mListener = listener;
}
public class MainActivity extends ActionBarActivity implements ClientListener {
#Override
public void onAction(){
....do whatever you need
}
...
}
You can pass an acvtivity reference to your client in either a constructor or a set accessor method.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(this);
try {
client.connect("192.168.1.10",5555);
} catch (IOException e) {
e.printStackTrace();
}
}
And in your java object:
MainActivity activity;
public Client(MainActivity activity) {
connected = false;
this.activity = activity;
}
...
public void run() {
String msg = ""; //holds the msg recieved from server
try {
while(connected && (msg = br.readLine())!= null)
{
//In Here I want to call MainActivity.displayServerAnswer()
activity.displayServerAnswer();
//notify observers//
this.setChanged();
//notify+send out recieved msg to Observers
this.notifyObservers(msg);
}
}
catch(IOException ioe) { }
finally { connected = false; }
}
How about passing the activity instance as an argument to the Client's constructor?
// MainActivity
Client client = new Client(this);
// Client
public Client(Activity activity) {
this.activity = activity;
connected = false;
}
i was made a bluetooth printer application (android based) for printing some text using datecs DPP-350 printer device. this program use a datecs external library such as bluetoohconnector and RFComm package. it works nicely, here's the code:
package com.myapp.MobilePrinter1;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import com.djarum.MobilePrinter1.BluetoothConnector;
import com.datecs.api.card.FinancialCard;
import com.datecs.api.printer.Printer;
import com.datecs.api.printer.PrinterInformation;
import com.datecs.api.printer.ProtocolAdapter;
import com.datecs.api.printer.ProtocolAdapter.Channel;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
public class MobilePrinter1Activity extends Activity {
public static final String CONNECTION_STRING = "connection_string";
private final Handler mHandler = new Handler();
private final Thread mConnectThread = new Thread() {
#Override
public void run() {
String connectionString = "bth://00:01:90:E6:40:52";
showProgress("Connecting");
if (connectionString.startsWith("bth://")) {
String address = connectionString.substring(6);
connectBth(address);
} else {
throw new IllegalArgumentException("Unsupported connection string");
}
dismissProgress();
}
void connectBth(String address) {
//setPrinterInfo(R.drawable.help, address);
try {
mBthConnector = BluetoothConnector.getConnector(MobilePrinter1Activity.this);
mBthConnector.connect(address);
mPrinter = getPrinter(
mBthConnector.getInputStream(),
mBthConnector.getOutputStream());
} catch (IOException e) {
//error(R.drawable.bluetooth, e.getMessage());
return;
}
mPrinterInfo = getPrinterInfo();
}
Printer getPrinter(InputStream in, OutputStream out) throws IOException {
ProtocolAdapter adapter = new ProtocolAdapter(in, out);
Printer printer = null;
if (adapter.isProtocolEnabled()) {
Channel channel = adapter.getChannel(ProtocolAdapter.CHANNEL_PRINTER);
InputStream newIn = channel.getInputStream();
OutputStream newOut = channel.getOutputStream();
printer = new Printer(newIn, newOut);
} else {
printer = new Printer(in, out);
}
return printer;
}
PrinterInformation getPrinterInfo() {
PrinterInformation pi = null;
try {
pi = mPrinter.getInformation();
//setPrinterInfo(R.drawable.printer, pi.getName());
} catch (IOException e) {
e.printStackTrace();
}
return pi;
}
};
private BluetoothConnector mBthConnector;
private Printer mPrinter;
private PrinterInformation mPrinterInfo;
private ProgressDialog mProgressDialog;
private BluetoothConnector mConnector;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try {
mConnector = BluetoothConnector.getConnector(this);
} catch (IOException e) {
Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT);
finish();
}
findViewById(R.id.button1).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
printText();
}
});
findViewById(R.id.button2).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
printBarcode();
}
});
findViewById(R.id.button3).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
printImage();
}
});
}
public void printText() {
new Thread() {
#Override
public void run() {
//showProgress(R.string.printing_text);
doPrintText2();
dismissProgress();
}
}.start();
}
public void printBarcode() {
new Thread() {
#Override
public void run() {
//showProgress(R.string.printing_text);
doPrintBarcode();
dismissProgress();
}
}.start();
}
public void printImage() {
new Thread() {
#Override
public void run() {
//showProgress(R.string.printing_text);
doPrintImage();
dismissProgress();
}
}.start();
}
#Override
protected void onStart() {
super.onStart();
mConnectThread.start();
}
#Override
protected void onStop() {
super.onStop();
if (mBthConnector != null) {
try {
mBthConnector.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void showProgress(final String text) {
mHandler.post(new Runnable() {
#Override
public void run() {
mProgressDialog = ProgressDialog.show(
MobilePrinter1Activity.this,
"Please wait",
text,
true);
}
});
}
private void showProgress(int resId) {
showProgress(getString(resId));
}
private void dismissProgress() {
mHandler.post(new Runnable() {
#Override
public void run() {
mProgressDialog.dismiss();
}
});
}
private void doPrintSelfTest() {
try {
mPrinter.printSelfTest();
} catch (IOException e) {
//error(R.drawable.selftest, getString(R.string.failed_print_self_test) + ". " +
//e.getMessage());
}
}
private void doPrintText2() {
EditText EditText1;
EditText1=(EditText)findViewById(R.id.editText1);
String temp;
try {
mPrinter.reset();
mPrinter.printTaggedText(EditText1.getText().toString());
//mPrinter.printTaggedText("Testing Testing!!");
mPrinter.feedPaper(110);
} catch (IOException e) {
//error(R.drawable.text, getString(R.string.failed_print_text) + ". " +
//e.getMessage());
}
}
private void doPrintBarcode() {
EditText EditText1;
EditText1=(EditText)findViewById(R.id.editText1);
try {
mPrinter.reset();
mPrinter.setBarcode(Printer.ALIGN_CENTER, false, 2, Printer.HRI_BOTH, 100);
mPrinter.printBarcode(Printer.BARCODE_CODE128, EditText1.getText().toString());
mPrinter.feedPaper(38);
mPrinter.feedPaper(110);
} catch (IOException e) {
//error(R.drawable.barcode, getString(R.string.failed_print_barcode) + ". " +
//e.getMessage());
}
}
private void doPrintImage() {
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.logo_djarum);
final int width = bitmap.getWidth();
final int height = bitmap.getHeight();
final int[] argb = new int[width * height];
bitmap.getPixels(argb, 0, width, 0, 0, width, height);
try {
mPrinter.reset();
mPrinter.printImage(argb, width, height, Printer.ALIGN_LEFT, true);
mPrinter.feedPaper(110);
} catch (IOException e) {
Toast.makeText(MobilePrinter1Activity.this, e.getMessage(), 1).show();
}
}
private void dialog(final int id, final String title, final String msg) {
mHandler.post(new Runnable() {
#Override
public void run() {
AlertDialog dlg = new AlertDialog.Builder(MobilePrinter1Activity.this)
.setTitle(title)
.setMessage(msg)
.create();
dlg.setIcon(id);
dlg.show();
}
});
}
private void error(final int resIconId, final String message) {
mHandler.post(new Runnable() {
#Override
public void run() {
AlertDialog dlg = new AlertDialog.Builder(MobilePrinter1Activity.this)
.setTitle("Error")
.setMessage(message)
.create();
dlg.setIcon(resIconId);
dlg.setOnDismissListener(new OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
MobilePrinter1Activity.this.finish();
}
});
dlg.show();
}
});
}
private void setPrinterInfo(final int resIconId, final String text) {
mHandler.post(new Runnable() {
#Override
public void run() {
//((ImageView)findViewById(R.id.icon)).setImageResource(resIconId);
//((TextView)findViewById(R.id.name)).setText(text);
}
});
}
}
the main problems now is how to call this program from phonegap? i've tried using droidGap but it will give me error when i start the printer's thread. has anyone know how to solved this?? many thanks..
I dont think that you can invoke too many APIs from the standard android browser (except some like location, contacts n all), but what is possible is other way round embedding a webview in a native app(which can be your above mentioned thread code) and invoking this code from a Javascript event using JavaScript Interface apis of android platform (which is pretty straight forward).