I'm trying to control my Arduino Mega with a Android Studio app via ethernet. The app has to send a json object with some variables to my Arduino. However, I can't get the connection to work and I can't find a clear answer on the internet.
Here's my code for the app
package com.example.ethernettest1;
import android.os.AsyncTask;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.SeekBar;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
SeekBar manueleSlider = (SeekBar)findViewById(R.id.manueleSlider);
manueleSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
int seekBarValue = 0;
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean b)
{
seekBarValue = progress;
}
#Override
public void onStartTrackingTouch(SeekBar seekBar)
{
// TODO Auto-generated method stub
}
#Override
public void onStopTrackingTouch(SeekBar seekBar)
{
// TODO Auto-generated method stub
}
});
JSONObject sendData = new JSONObject();
{
try {
sendData.put("seekBarValue", seekBarValue);
} catch (JSONException e) {
e.printStackTrace();
}
}
if (sendData.length() > 0) {
new Background_get().execute(String.valueOf(sendData));
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/*****************************************************/
/* This is a background process for connecting */
/* to the arduino server and sending */
/* the GET request withe the added data */
/*****************************************************/
class Background_get extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
try {
/*********************************************************/
/* Change the IP to the IP you set in the arduino sketch */
/*********************************************************/
URL url = new URL("http://192.168.1.177/?" + params[0]);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder result = new StringBuilder();
String inputLine;
while ((inputLine = in.readLine()) != null)
result.append(inputLine).append("\n");
in.close();
connection.disconnect();
return result.toString();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
}
And this is the code for the Arduino
#include <ArduinoJson.h>
#include <SPI.h>
#include <Ethernet.h>
const size_t capacity = JSON_OBJECT_SIZE(1) + 20;
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
IPAddress ip(192, 168, 1, 177);
EthernetServer server(80);
void setup()
{
pinMode(34, OUTPUT);
Ethernet.init(10);
Serial.begin(9600);
Ethernet.begin(mac, ip);
server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}
void loop() {
// listen for incoming clients
EthernetClient client = server.available();
if (client) {
Serial.println("new client");
// an http request ends with a blank line
boolean currentLineIsBlank = true;
String buffer = "";
while (client.connected()) {
if (client.available()) {
char c = client.read();
buffer += c;
if (c == '\n' && currentLineIsBlank)
{
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close"); // the connection will be closed after completion of the response
client.println("Refresh: 5"); // refresh the page automatically every 5 sec
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.println("test");
client.println(buffer);
break;
}
if (c == '\n')
{
// you're starting a new line
currentLineIsBlank = true;
DeserializationError error = deserializeJson(doc, buffer);
if(error) {
Serial.print("deserializeJson() failed with code ");
Serial.println(error.c_str());
return;
}
int slider = doc["seekBarValue"];
if(slider > 0)
{
digitalWrite(34, HIGH);
delay(2000);
digitalWrite(34, LOW);
delay(2000);
}
}
else if (c != '\r')
{
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
Serial.println("client disconnected");
}
}
From the comments, I think there is a problem with your SeekBar implementation not refecting on the value being sent as the code only runs once.
Here's the modified part of the code :
SeekBar manueleSlider = (SeekBar)findViewById(R.id.manueleSlider);
manueleSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean b)
{
}
#Override
public void onStartTrackingTouch(SeekBar seekBar)
{
// TODO Auto-generated method stub
}
#Override
public void onStopTrackingTouch(SeekBar seekBar)
{
JSONObject sendData = new JSONObject();
{
try
{
sendData.put("seekBarValue", seekBar.getProgress()); // directly get the progress
}
catch (JSONException e)
{
e.printStackTrace();
}
}
if (sendData.length() > 0)
{
new Background_get().execute(String.valueOf(sendData));
}
}
});
Related
I am trying to control an arduino micro controller from android phone.
I need help to to continuously receive the output from the temperature sensor and display it on text view.
Here is the code:
package com.war10ck6001gmail.finalproject;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.TextView;
import android.widget.ToggleButton;
public class MainActivity extends ActionBarActivity {
public ToggleButton fan, light, manauto;
public Button inc, dec;
public TextView temp;
public Toolbar mToolbar;
TCPClient mTcpClient = null;
public connectTask conctTask = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
// connect to the server
temp = (TextView) findViewById(R.id.temprature);
fan = (ToggleButton) findViewById(R.id.fanbutton);
light = (ToggleButton) findViewById(R.id.lightbutton);
manauto = (ToggleButton) findViewById(R.id.manauto);
inc = (Button) findViewById(R.id.increment);
dec = (Button) findViewById(R.id.decrement);
Automatic(light);
Automatic(fan);
Automatic(inc);
Automatic(dec);
conctTask = new connectTask();
conctTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
mTcpClient = null;
manauto.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
Manual(light);
Manual(fan);
Manual(inc);
Manual(dec);
mTcpClient.sendMessage("Man");
}
else {
Automatic(light);
Automatic(fan);
Automatic(inc);
Automatic(dec);
mTcpClient.sendMessage("Auto");
}
}
});
light.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
mTcpClient.sendMessage("0");
}
else {
mTcpClient.sendMessage("1");
}
}
});
fan.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
mTcpClient.sendMessage("2");
}
else {
mTcpClient.sendMessage("3");
}
}
});
inc.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mTcpClient.sendMessage("4");
}
});
dec.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mTcpClient.sendMessage("5");
}
});
}
public void Automatic(Button btn) {
btn.setEnabled(false);
btn.getBackground().setColorFilter(Color.GRAY, PorterDuff.Mode.MULTIPLY);
}
public void Manual(Button btn) {
btn.setEnabled(true);
btn.getBackground().setColorFilter(null);
}
public class connectTask extends AsyncTask<String, String, TCPClient> {
String finalmessage;
#Override
protected TCPClient doInBackground(final String... message) {
//we create a TCPClient object and
mTcpClient = new TCPClient(new TCPClient.OnMessageReceived() {
#Override
//here the messageReceived method is implemented
public void messageReceived(final String message) {
try {
//this method calls the onProgressUpdate
//publishProgress(message);
if (message != null) {
//finalmessage = message;
runOnUiThread(new Runnable() {
#Override
public void run() {
temp.setText(message);
}
});
System.out.println("Return Message from Socket::::: >>>>> " + message);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
});
mTcpClient.run();
if (mTcpClient != null) {
mTcpClient.sendMessage("Initial Message when connected with Socket Server");
}
/* runOnUiThread(new Runnable() {
#Override
public void run() {
temp.setText(finalmessage);
}
});*/
return null;
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
return true;
}
if (id == R.id.action_master) {
return true;
}
if (id == R.id.action_bedroom) {
Intent intent = new Intent(getApplicationContext(), Bedroom.class);
startActivity(intent);
return true;
}
if (id == R.id.action_Cbedroom) {
Intent intent = new Intent(getApplicationContext(), Cbedroom.class);
startActivity(intent);
return true;
}
if (id == R.id.action_diningroom) {
Intent intent = new Intent(getApplicationContext(), Diningroom.class);
startActivity(intent);
return true;
}
return super.onOptionsItemSelected(item);
}
}
here is the class which has the onmessage recieved
public class TCPClient {
public String serverMessage;
/**
* Specify the Server Ip Address here. Whereas our Socket Server is started.
*/
public static final String SERVERIP = "10.5.38.148"; // your computer IP address
public static final int SERVERPORT = 8888;
private OnMessageReceived mMessageListener = null;
private boolean mRun = false;
private PrintWriter out = null;
private BufferedReader in = null;
MainActivity mainActivity = null;
/**
* Constructor of the class. OnMessagedReceived listens for the messages received from server
*/
public TCPClient(final OnMessageReceived listener) {
mMessageListener = listener;
}
/**
* Sends the message entered by client to the server
*
* #param message text entered by client
*/
public void sendMessage(String message) {
if (out != null && !out.checkError()) {
System.out.println("message: " + message);
out.println(message);
out.flush();
}
}
public void stopClient() {
mRun = false;
}
public void run() {
mRun = true;
while (mRun) {
try {
//here you must put your computer's IP address.
InetAddress serverAddr = InetAddress.getByName(SERVERIP);
Log.e("TCP SI Client", "SI: Connecting...");
//create a socket to make the connection with the server
Socket socket = new Socket(serverAddr, SERVERPORT);
try {
//send the message to the server
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
Log.e("TCP SI Client", "SI: Sent.");
Log.e("TCP SI Client", "SI: Done.");
//receive the message which the server sends back
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//in this while the client listens for the messages sent by the server
serverMessage = in.readLine();
if (serverMessage != null && mMessageListener != null) {
//call the method messageReceived from MyActivity class
mMessageListener.messageReceived(serverMessage);
Log.e("RESPONSE FROM SERVER", "S: Received Message: '" + serverMessage + "'");
}
serverMessage = null;
}
catch (Exception e) {
Log.e("TCP SI Error", "SI: Error", e);
e.printStackTrace();
}
finally {
//the socket must be closed. It is not possible to reconnect to this socket
// after it is closed, which means a new socket instance has to be created.
socket.close();
}
}
catch (Exception e) {
Log.e("TCP SI Error", "SI: Error", e);
}
}
}
//Declare the interface. The method messageReceived(String message) will must be implemented in the MyActivity
//class at on asynckTask doInBackground
public interface OnMessageReceived {
public void messageReceived(String message);
}
}
I have 3 buttons to turn on a different led, using wifi. What am I trying to do is to start a thread when a button is pressed. The thread will do a networking stuff which is to send a String of instruction code. But when I pressed the button, it stops running. And I want to display the exception in the toast if there is an exception occured. Please help.
Here is the code:
This is the activity that will display 3 buttons.
package com.gfhz.appliancecontrol;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
public class LightsMenuActivity extends MainActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lights_menu);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.display_lights_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private void checkLightsStatus() {
/*instructionID = "0400";
Intent intent = new Intent(this, ConnectionSocket.class);
intent.putExtra(INSTRUCTION, instructionID);
startActivity(intent);*/
}
public void powerLamp1 (View view) {
ConnectionSocket cs = new ConnectionSocket();
cs.sendInstruction("0401");
}
public void powerLamp2(View view) {
ConnectionSocket cs = new ConnectionSocket();
cs.sendInstruction("0402");
}
public void powerLamp3(View view){
ConnectionSocket cs = new ConnectionSocket();
cs.sendInstruction("0403");
}
}
And this is the activity that will execute the thread.
package com.gfhz.appliancecontrol;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import android.app.Activity;
import android.widget.Toast;
public class ConnectionSocket extends Activity{
Socket client;
ConnectionInfoActivity conInfo;
String instructionCode;
String serverAddr;
OutputStream os;
DataOutputStream dos;
String stoast;
public void sendInstruction (String instruction) {
// Get the DEVICE ID
String devId = conInfo.getDevId();
// Concatenate instruction message and device Id
instructionCode = devId.concat(instruction);
// Get the SERVER IP ADDRESS
serverAddr = "192.168.1.105";
// Initialize PORT
final int port = 2000;
new Thread (new Runnable() {
public void run() {
try{
// Open a socket
client = new Socket(serverAddr, port);
dos = new DataOutputStream(client.getOutputStream());
dos.writeBytes(instructionCode);
} catch (UnknownHostException e) {
//TODO Auto-generated catch block
e.printStackTrace();
stoast = "Unknown Host Exception" + e.toString();
} catch (IOException e) {
// TODO Auto-generated cach block
e.printStackTrace();
// Display in TOAST
stoast = "IO Exception" + e.toString();
} finally {
if (client != null) {
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}).start();
Toast.makeText(getApplicationContext(), stoast, Toast.LENGTH_SHORT).show();
}
}
I am sending some data to an android application over UDP. Therefore i created the following UDPReceiver-Class:
package com.example.urowatch;
import java.net.*;
import java.nio.ByteBuffer;
import java.io.*;
public class UDPReceiver extends Thread
{
private DatagramSocket m_Socket;
private int m_BufferSize;
private Boolean m_End = false;
private int m_TotalLength;
private int m_Received;
private byte[] m_Buffer;
private byte[] m_Result;
private Boolean m_IsNewResult = false;
private float m_Progress;
private int m_ImageCount = 0;
private int m_FrameErrors = 0;
public UDPReceiver(String name, int port, int bufferSize) throws IOException
{
super(name);
m_Socket = new DatagramSocket(port);
m_BufferSize = bufferSize;
m_Socket.setBroadcast(true);
m_Socket.setReceiveBufferSize(m_BufferSize);
}
public void run()
{
while(!m_End)
{
try
{
byte[] buf = new byte[m_BufferSize];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
m_Socket.receive(packet);
ProcessData(packet);
}
catch (IOException e)
{
if (!m_Socket.isClosed())
e.printStackTrace();
}
}
}
private void ProcessData(DatagramPacket packet)
{
if (packet.getLength() == 4)
{
ByteBuffer bb = ByteBuffer.wrap(packet.getData());
m_TotalLength = bb.getInt();
if (m_Received != 0)
m_FrameErrors++;
m_Received = 0;
m_Buffer = new byte[m_TotalLength];
}
else if (m_Buffer != null && m_Received != m_TotalLength)
{
int length = packet.getLength();
System.arraycopy(packet.getData(), 0, m_Buffer, m_Received, length);
m_Received += length;
m_Progress = 100 * (float)m_Received/(float)m_TotalLength;
if (m_Received == m_TotalLength)
{
m_Result = new byte[m_TotalLength];
System.arraycopy(m_Buffer, 0, m_Result, 0, m_TotalLength);
m_IsNewResult = true;
m_ImageCount++;
m_Received = 0;
}
}
}
public Boolean IsNewResult()
{
return m_IsNewResult;
}
public byte[] GetResult()
{
m_IsNewResult = false;
return m_Result;
}
public float GetProgress()
{
return m_Progress;
}
public float GetRatio()
{
return 100 * (float)m_ImageCount / (float)m_FrameErrors;
}
public void stopServer()
{
m_End = true;
if (m_Socket != null)
m_Socket.close();
}
}
And i am using this class like this:
package com.example.urowatch;
import java.io.IOException;
import java.text.DecimalFormat;
import android.os.*;
import android.app.Activity;
import android.app.AlertDialog;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import android.support.v4.app.NavUtils;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.os.Build;
public class LiveActivity extends Activity {
private static ImageView m_ImageView1;
private static TextView m_TextView1;
private static DecimalFormat m_DF;
private static Context m_Context;
private UDPReceiver m_Receiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_live);
// Show the Up button in the action bar.
setupActionBar();
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
m_ImageView1 = (ImageView)findViewById(R.id.imageView1);
m_TextView1 = (TextView)findViewById(R.id.textView1);
m_Context = this;
m_DF = new DecimalFormat("00.00");
}
/**
* Set up the {#link android.app.ActionBar}, if the API is available.
*/
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void setupActionBar() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
getActionBar().setDisplayHomeAsUpEnabled(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.live, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// This ID represents the Home or Up button. In the case of this
// activity, the Up button is shown. Use NavUtils to allow users
// to navigate up one level in the application structure. For
// more details, see the Navigation pattern on Android Design:
//
// http://developer.android.com/design/patterns/navigation.html#up-vs-back
//
NavUtils.navigateUpFromSameTask(this);
return true;
}
return super.onOptionsItemSelected(item);
}
private static Handler MyHandler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
if (msg.what == 100)
{
float[] infos = (float[])msg.obj;
m_TextView1.setText("Empfange Bild: " + m_DF.format(infos[0]) + "% (FrameErrors: " + m_DF.format(infos[1]) + "%)");
}
else if (msg.what == 101)
{
byte[] b = (byte[])msg.obj;
m_TextView1.setText("Empfange Bild: 100,00%");
m_ImageView1.setImageBitmap(BitmapFactory.decodeByteArray(b, 0, b.length));
}
else if (msg.what == 102)
{
AlertDialog.Builder b = new AlertDialog.Builder(m_Context);
b.setTitle("Fehler");
b.setMessage("Es ist folgende Exception aufgetreten:\n" + (Exception)msg.obj);
b.setNeutralButton("OK", null);
b.show();
}
}
};
#Override
public void onBackPressed() {
super.onBackPressed();
if (m_Receiver != null)
m_Receiver.stopServer();
finish();
}
#Override
public void onPause()
{
m_Receiver.stopServer();
super.onPause();
}
#Override
protected void onResume()
{
try {
m_Receiver = new UDPReceiver("UDPReceiver", 5678, 1024);
m_Receiver.start();
} catch (IOException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
AlertDialog.Builder b = new AlertDialog.Builder(this);
b.setTitle("Fehler");
b.setMessage("Es ist folgende Exception aufgetreten:\n" + e1);
b.setNeutralButton("OK", null);
b.show();
}
// Thread thread = new Thread()
// {
// #Override
// public void run()
// {
// while(true)
// {
// try {
//sleep(250);
Toast.makeText(getBaseContext(), "Runing Thread", Toast.LENGTH_SHORT).show();
Update();
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// MyHandler.sendMessage(MyHandler.obtainMessage(102, e));
// }
// }
// }
// };
// thread.start();
super.onResume();
}
public void buttonClick(View v)
{
Update();
}
private void Update()
{
if (m_Receiver != null)
{
if (m_Receiver.IsNewResult())
{
byte[] b = m_Receiver.GetResult();
MyHandler.sendMessage(MyHandler.obtainMessage(101, b));
}
else
{
float[] infos = new float[2];
infos[0] = m_Receiver.GetProgress();
infos[1] = m_Receiver.GetRatio();
MyHandler.sendMessage(MyHandler.obtainMessage(100, infos));
}
}
}
}
As you see i want to check the status of the UDPReceiver-Object (Is there a new complete byte[] ready?) by a thread. To update the GUI, the thread has to send a Message to MyHandler which will update the GUI.
In the moment i have to to click a button to raise the buttonClick-Event. Later on i want to do this in the commented thread-structure.
Now, here's my problem:
I start the Activity and everything works fine. Then i am starting to send ONE packet manually with my UDP-Sender (which works, i validated it with a C#-UDP-Receiver). The first packet get received fine. Then i send the second packet which get received, too. But from now on, my breakpoint at m_Socket.receive(packet); wont get hit anymore!
I have NO idea what this behaviour causes and it is very important for me to make this application work.
Please, if you have ANY Idea or just a guess, please let me know.
I am trying to develop a application. It is a radio application. When i use a method to show meta data that time it is creating some problem.
1.Play Pause button are not working smoothly.
2.Taking more time to show layout.
here is the main activity code:
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.ImageButton;
import android.widget.TextView;
public class IRadioActivity extends Activity implements
MediaPlayer.OnCompletionListener, MediaPlayer.OnPreparedListener,
MediaPlayer.OnErrorListener, MediaPlayer.OnBufferingUpdateListener {
private String TAG = getClass().getSimpleName();
private MediaPlayer mp = null;
private ImageButton btnPlay;
String title;
String artist;
private static Context con;
Timer timer;
TextView StationName;
String Stationurl = "http://95.211.82.139:8048";
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
IRadioActivity.con = this;
btnPlay = (ImageButton) findViewById(R.id.btnPlay);
mp = new MediaPlayer();
mp.setOnCompletionListener(this); // Important
btnPlay.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
// check for already playing
if (mp.isPlaying()) {
if (mp != null) {
mp.pause();
// Changing button image to play button
btnPlay.setImageResource(R.drawable.btn_play);
}
} else {
// Resume song
if (mp != null) {
mp.start();
// Changing button image to pause button
btnPlay.setImageResource(R.drawable.btn_pause);
}
}
}
});
playSong();
getMeta();
}
public void playSong() {
// Play song
try {
mp.reset();
mp.setDataSource(Stationurl);
mp.prepare();
mp.start();
// Displaying Song title
// Changing Button Image to pause image
btnPlay.setImageResource(R.drawable.btn_pause);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void onDestroy() {
super.onDestroy();
mp.release();
}
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
}
// ----------------
public boolean onError(MediaPlayer mp, int what, int extra) {
StringBuilder sb = new StringBuilder();
sb.append("Media Player Error: ");
switch (what) {
case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
sb.append("Not Valid for Progressive Playback");
break;
case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
sb.append("Server Died");
break;
case MediaPlayer.MEDIA_ERROR_UNKNOWN:
sb.append("Unknown");
break;
default:
sb.append(" Non standard (");
sb.append(what);
sb.append(")");
}
sb.append(" (" + what + ") ");
sb.append(extra);
Log.e(TAG, sb.toString());
return true;
}
public void onBufferingUpdate(MediaPlayer mp, int percent) {
Log.d(TAG, "PlayerService onBufferingUpdate : " + percent + "%");
}
// .....top bar button....//
public void getMeta() {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
URL url;
// Message msg = handler.obtainMessage();
try {
// url = new URL("http://relay5.slayradio.org:8000");
url = new URL(Stationurl);
final IcyStreamMeta icy = new IcyStreamMeta(url);
runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
// Typeface book = Typeface.createFromAsset(
// getAssets(), "fonts/Neutra2Text-Book.otf");
final TextView songTitle = (TextView) findViewById(R.id.songName);
final TextView artistName = (TextView) findViewById(R.id.artistName);
try {
artistName.setText(icy.getArtist().toString()
.trim());
artistName.setText(icy.getArtist().toString()
.trim());
songTitle.setText(icy.getTitle().toString()
.trim());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, 0, 500);
}
#Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
}
}
Facing those problems when i use getMeta(); method.
Main Class for this method is:
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class IcyStreamMeta<Message> {
protected URL streamUrl;
private Map<String, String> metadata;
private boolean isError;
public IcyStreamMeta(URL streamUrl) {
setStreamUrl(streamUrl);
isError = false;
}
/**
* Get artist using stream's title
*
* #return String
* #throws IOException
*/
public String getArtist() throws IOException {
Map<String, String> data = getMetadata();
if (!data.containsKey("StreamTitle"))
return "";
String streamTitle = data.get("StreamTitle");
String title = streamTitle.substring(0, streamTitle.indexOf("-"));
return title.trim();
}
/**
* Get title using stream's title
*
* #return String
* #throws IOException
*/
public String getTitle() throws IOException {
Map<String, String> data = getMetadata();
if (!data.containsKey("StreamTitle"))
return "";
String streamTitle = data.get("StreamTitle");
String artist = streamTitle.substring(streamTitle.indexOf("-")+1);
return artist.trim();
}
public Map<String, String> getMetadata() throws IOException {
if (metadata == null) {
refreshMeta();
}
return metadata;
}
public void refreshMeta() throws IOException {
retreiveMetadata();
}
private void retreiveMetadata() throws IOException {
URLConnection con = streamUrl.openConnection();
con.setRequestProperty("Icy-MetaData", "1");
con.setRequestProperty("Connection", "close");
con.setRequestProperty("Accept", null);
con.connect();
int metaDataOffset = 0;
Map<String, List<String>> headers = con.getHeaderFields();
InputStream stream = con.getInputStream();
if (headers.containsKey("icy-metaint")) {
// Headers are sent via HTTP
metaDataOffset = Integer.parseInt(headers.get("icy-metaint").get(0));
} else {
// Headers are sent within a stream
StringBuilder strHeaders = new StringBuilder();
char c;
while ((c = (char)stream.read()) != -1) {
strHeaders.append(c);
if (strHeaders.length() > 5 && (strHeaders.substring((strHeaders.length() - 4), strHeaders.length()).equals("\r\n\r\n"))) {
// end of headers
break;
}
}
// Match headers to get metadata offset within a stream
Pattern p = Pattern.compile("\\r\\n(icy-metaint):\\s*(.*)\\r\\n");
Matcher m = p.matcher(strHeaders.toString());
if (m.find()) {
metaDataOffset = Integer.parseInt(m.group(2));
}
}
// In case no data was sent
if (metaDataOffset == 0) {
isError = true;
return;
}
// Read metadata
int b;
int count = 0;
int metaDataLength = 4080; // 4080 is the max length
boolean inData = false;
StringBuilder metaData = new StringBuilder();
// Stream position should be either at the beginning or right after headers
while ((b = stream.read()) != -1) {
count++;
// Length of the metadata
if (count == metaDataOffset + 1) {
metaDataLength = b * 16;
}
if (count > metaDataOffset + 1 && count < (metaDataOffset + metaDataLength)) {
inData = true;
} else {
inData = false;
}
if (inData) {
if (b != 0) {
metaData.append((char)b);
}
}
if (count > (metaDataOffset + metaDataLength)) {
break;
}
}
// Set the data
metadata = IcyStreamMeta.parseMetadata(metaData.toString());
// Close
stream.close();
}
public boolean isError() {
return isError;
}
public URL getStreamUrl() {
return streamUrl;
}
public void setStreamUrl(URL streamUrl) {
this.metadata = null;
this.streamUrl = streamUrl;
this.isError = false;
}
public static Map<String, String> parseMetadata(String metaString) {
Map<String, String> metadata = new HashMap();
String[] metaParts = metaString.split(";");
Pattern p = Pattern.compile("^([a-zA-Z]+)=\\'([^\\']*)\\'$");
Matcher m;
for (int i = 0; i < metaParts.length; i++) {
m = p.matcher(metaParts[i]);
if (m.find()) {
metadata.put((String)m.group(1), (String)m.group(2));
}
}
return metadata;
}
}
Use prepareAsync() and not prepare(). See the documentation here: http://developer.android.com/guide/topics/media/mediaplayer.html#preparingasync
I'm using a Freeduino (Arduino Uno compatible) with a Samsung Galaxy Tab 10.1 running ICS (4) and I have succeeded in writing from the Arduino to the Android, but I have not been able to read from the Android in the Arduino sketch.
Here's the Android class for the USB Accessory:
package com.kegui.test;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.io.Writer;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.util.ArrayList;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import com.kegui.test.Scripto;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class USBAccess extends Activity implements Runnable, OnClickListener {
private static final String ACTION_USB_PERMISSION = "com.google.android.DemoKit.action.USB_PERMISSION";
protected static final String TAG = "KegUI";
private UsbManager mUsbManager;
private PendingIntent mPermissionIntent;
private boolean mPermissionRequestPending;
private TextView debugtext = null;
private Button button1 = null;
private Button button2 = null;
private boolean button2visible = false;
UsbAccessory mAccessory;
ParcelFileDescriptor mFileDescriptor;
FileInputStream mInputStream;
FileOutputStream mOutputStream;
private static final int MESSAGE_BUTTON_PRESSED = 1;
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.i("KegApp", "***********************Received*************************");
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
if (intent.getBooleanExtra(
UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
openAccessory(accessory);
} else {
Log.d(TAG, "permission denied for accessory "
+ accessory);
}
mPermissionRequestPending = false;
}
} else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
if (accessory != null && accessory.equals(mAccessory)) {
closeAccessory();
}
}
}
};
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(
ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
setContentView(R.layout.main);
final Button button = (Button) findViewById(R.id.button1);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on click
new TempUpdateTask().execute("testing");
}
});
registerReceiver(mUsbReceiver, filter);
Log.d(TAG,"on Create'd");
}
#Override
public void onResume() {
super.onResume();
if (mInputStream != null && mOutputStream != null) {
return;
}
UsbAccessory[] accessories = mUsbManager.getAccessoryList();
UsbAccessory accessory = (accessories == null ? null : accessories[0]);
if (accessory != null) {
if (mUsbManager.hasPermission(accessory)) {
openAccessory(accessory);
} else {
synchronized (mUsbReceiver) {
if (!mPermissionRequestPending) {
mUsbManager.requestPermission(accessory,
mPermissionIntent);
mPermissionRequestPending = true;
}
}
}
} else {
Log.d(TAG, "mAccessory is null");
}
}
#Override
public void onPause() {
super.onPause();
closeAccessory();
}
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(mUsbReceiver);
}
private void openAccessory(UsbAccessory accessory) {
mFileDescriptor = mUsbManager.openAccessory(accessory);
if (mFileDescriptor != null) {
mAccessory = accessory;
FileDescriptor fd = mFileDescriptor.getFileDescriptor();
mInputStream = new FileInputStream(fd);
mOutputStream = new FileOutputStream(fd);
Thread thread = new Thread(null, this, "KegApp");
thread.start();
//enableControls(true);
} else {
Log.d(TAG, "accessory open fail");
}
}
public void run() {
int ret = 0;
byte[] buffer = new byte[16384];
int i;
Log.i("KegApp", "***********************in run*************************");
while (ret >= 0) {
try {
ret = mInputStream.read(buffer); // this will be always positive, as long as the stream is not closed
} catch (IOException e) {
break;
}
i = 0;
while (i < ret) {
Message m = Message.obtain(messageHandler, MESSAGE_BUTTON_PRESSED);
m.obj = buffer[i];
messageHandler.sendMessage(m);
i++;
}
}
}
private void closeAccessory() {
//enableControls(false);
try {
if (mFileDescriptor != null) {
mFileDescriptor.close();
}
} catch (IOException e) {
} finally {
mFileDescriptor = null;
mAccessory = null;
}
}
public void sendCommand(FileOutputStream mStream) {
BufferedOutputStream bo = new BufferedOutputStream(mStream);
// if (mStream != null && message.length > 0) {
try {
Log.i("KegApp", "***********************sending command now*************************");
bo.write(1); //message, 0, 3);
} catch (IOException e) {
Log.e(TAG, "write failed", e);
}
// }
}
#Override
public void onClick(View v) {
// Send some message to Arduino board, e.g. "13"
Log.e(TAG, "write failed");
}
// Instantiating the Handler associated with the main thread.
private Handler messageHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
Log.i("KegApp", "***********************message handler before " + msg.what + "************************");
try {
String load = msg.obj.toString();
Log.i("KegApp", "***********************in message handler*************************");
/*
if (button2visible==false) {
debugtext.setText("Received message: "+String.valueOf(load));
button2.setVisibility(View.VISIBLE);
button2visible = true;
} else {
debugtext.setText("");
button2.setVisibility(View.GONE);
button2visible = false;
}
*/
new TempUpdateTask().execute(load);
} catch (Exception e) {
Log.e(TAG, "message failed", e);
}
}
};
// UpdateData Asynchronously sends the value received from ADK Main Board.
// This is triggered by onReceive()
class TempUpdateTask extends AsyncTask<String, String, String> {
// Called to initiate the background activity
protected String doInBackground(String... sensorValue) {
try {
Log.i("KegApp", "***********************calling sendcommand*********************");
sendCommand(mOutputStream);
Log.i("KegApp", "*********************incoming-sensorValue*********************" );
ArduinoMessage arduinoMessage = new ArduinoMessage(sensorValue[0]);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String returnString = String.valueOf(sensorValue[0]);//String.valueOf(sensorValue[0]) + " F";
publishProgress(String.valueOf(sensorValue[0]));
return (returnString); // This goes to result
}
// Called when there's a status to be updated
#Override
protected void onProgressUpdate(String... values) {
// Init TextView Widget to display ADC sensor value in numeric.
TextView tvAdcvalue = (TextView) findViewById(R.id.tvTemp);
tvAdcvalue.setText(String.valueOf(values[0]));
// Not used in this case
}
// Called once the background activity has completed
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
closeAccessory();
}
}
}
Here's my Arduino Sketch:
#include <FHB.h>
#include <Max3421e.h>
#include <Max3421e_constants.h>
#include <Max_LCD.h>
#include <Usb.h>
//FREEDUINO ONLY------------------------------------
//END FREEDUINO ONLY------------------------------------
int pin_light_sensor_1=A0;
int pin_output_sensor=9;
int currLightLevel=0;
//int prevLightLevel=0;
//int lightStableRange=90;
int delayTime=3000;
int loopCtr=0;
char cSTX=char(2);
char cSOH=char(1);
char cEOT=char(4);
char cGS=char(29);
char cRS=char(30);
char cCR=char(13);
char cLF=char(10);
//FREEDUINO ONLY------------------------------------
AndroidAccessory acc("Company Inc.",
"Kegbot5K datawriter",
"Kegbot 5000 data writer",
"1.0",
"http://companyinc.com",
"0000000012345678");
//END FREEDUINO ONLY------------------------------------
void setup()
{
pinMode(pin_light_sensor_1, INPUT);
pinMode(pin_output_sensor, OUTPUT);
Serial.begin(57600);
//FREEDUINO ONLY------------------------------------
Serial.println("pre-power");
acc.powerOn();
Serial.println("post-power");
//END FREEDUINO ONLY------------------------------------
}
void loop()
{
byte msg[3];
if (acc.isConnected()) {
currLightLevel = analogRead(pin_light_sensor_1);
//sysPrint(delayTime*loopCtr);
//sysPrint(",");
//sysPrint(currLightLevel);
writeDataMessage("LGH01", currLightLevel);
}
delay(1000);
if (acc.isConnected()) {
int len = acc.read(msg, sizeof(msg), 1);
Serial.println(len);
if (len > 0){
for (int index=0; index < len; index++){
digitalWrite(pin_output_sensor, 1);
delay(500);
digitalWrite(pin_output_sensor, 0);
}
}
}
loopCtr++;
delay(delayTime);
}
void writeHeader(String msgType)
{
sysPrint(cSTX);
sysPrint(cSTX);
sysPrint(cSOH);
sysPrint(msgType);
sysPrint(cGS);
}
void writeFooter()
{
sysPrint(cEOT);
sysPrintLn(cEOT);
}
void writeDataMessage(String sensorID, int value)
{
writeHeader("DATA");
sysPrint(sensorID);
sysPrint(cRS);
sysPrint(value);
writeFooter();
}
void writeAlarmMessage(String sensorID, String message)
//Do we need to enforce the 5 char sensorID here? I don't think so...
{
writeHeader("ALRM");
sysPrint(sensorID);
sysPrint(cRS);
sysPrint(message);
writeFooter();
}
void sysPrint(String whatToWrite)
{
int len=whatToWrite.length();
char str[len];
whatToWrite.toCharArray(str, len);
acc.write((void *)str, len);
// acc.write(&whatToWrite, whatToWrite.length());
}
void sysPrint(char whatToWrite)
{
acc.write((void *)whatToWrite, 1);
// acc.write(&whatToWrite, 1);
}
void sysPrint(int whatToWrite)
{
acc.write((void *)&whatToWrite, 1);
// acc.write(&whatToWrite, 1);
}
void sysPrintLn(String whatToWrite)
{
int len=whatToWrite.length();
char str[len];
whatToWrite.toCharArray(str, len);
acc.write((void *)str, len);
acc.write((void *)&cCR, 1);
acc.write((void *)&cLF, 1);
// acc.write(&whatToWrite, whatToWrite.length());
// acc.write(&cCR, 1);
// acc.write(&cLF, 1);
}
void sysPrintLn(char whatToWrite)
{
acc.write((void *)whatToWrite, 1);
acc.write((void *)&cCR, 1);
acc.write((void *)&cLF, 1);
// acc.write(&whatToWrite, 1);
// acc.write(&cCR, 1);
// acc.write(&cLF, 1);
}
The sendCommand function in the Android is logging that it was sent. The acc.read function is printing length to Serial output as -1, as in no input. Speaking of which, the Android logs do not show errors, so I'm thinking this might be an Arduino thing.
My Manifest has an Intent filter that's registering the device, although permissions might have something to do with it.
<intent-filter>
<action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
</intent-filter>
<meta-data android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
android:resource="#xml/accessory_filter" />
</activity>
Thanks in advance for any thoughts,
Sara
I have developed an RC helicopter that can be controlled using android by sending messages from the android to the arduino located on top of the Helicopter using Bluetooth Stick, i did not use usb yet for any project but when you are sending messages to the arduino you are using serial communication weather connected threw USB or Bluetooth i suggest to simply use Serial.read and every message you send to arduino end it with some symbol '#' for example just to separate messages and get the message character by character
this is the code to read the full message ended with '#' from the Serial port:
String getMessage()
{
String msg=""; //the message starts empty
byte ch; // the character that you use to construct the Message
byte d='#';// the separating symbol
if(Serial.available())// checks if there is a new message;
{
while(Serial.available() && Serial.peek()!=d)// while the message did not finish
{
ch=Serial.read();// get the character
msg+=(char)ch;//add the character to the message
delay(1);//wait for the next character
}
ch=Serial.read();// pop the '#' from the buffer
if(ch==d) // id finished
return msg;
else
return "NA";
}
else
return "NA"; // return "NA" if no message;
}
this function checks if there any message in the buffer if not it returns "NA".
if that did not help please inform.
Figured out what's going wrong - sendCommand is executing from the asynchronous TempTask so it doesn't get passed a valid reference to the FileOutputStream. I can execute sendCommand onClick from the main thread and receive on the Arduino just fine.