This has been the method so far to send and receive on bluetooth using Java with threading. But how do we do this using Kotlin's latest Coroutines? Alot of this old Java cold no longer translates to Kotlin 1.4+ either in terms of how to do threading. I read Kotlin is now using Coroutines instead of threads like before.
public class MainActivity extends AppCompatActivity {
private static final UUID MY_UUID_INSECURE =
UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66")
public void pairDevice(View v) {
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
Object[] devices = pairedDevices.toArray();
BluetoothDevice device = (BluetoothDevice) devices[0]
ConnectThread connect = new ConnectThread(device,MY_UUID_INSECURE);
connect.start();
}
}
private class ConnectThread extends Thread {
private BluetoothSocket mmSocket;
public ConnectThread(BluetoothDevice device, UUID uuid) {
mmDevice = device;
deviceUUID = uuid;
}
public void run(){
BluetoothSocket tmp = null;
// Get a BluetoothSocket for a connection with the
// given BluetoothDevice
try {
tmp = mmDevice.createRfcommSocketToServiceRecord(MY_UUID_INSECURE);
} catch (IOException e) {
}
mmSocket = tmp;
try {
// This is a blocking call and will only return on a
// successful connection or an exception
mmSocket.connect();
} catch (IOException e) {
// Close the socket
try {
mmSocket.close();
} catch (IOException e1) {
}
}
//will talk about this in the 3rd video
connected(mmSocket);
}
}
private void connected(BluetoothSocket mmSocket) {
// Start the thread to manage the connection and perform transmissions
mConnectedThread = new ConnectedThread(mmSocket);
mConnectedThread.start();
}
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
try {
tmpIn = mmSocket.getInputStream();
tmpOut = mmSocket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run(){
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
// Read from the InputStream
try {
bytes = mmInStream.read(buffer);
final String incomingMessage = new String(buffer, 0, bytes);
runOnUiThread(new Runnable() {
#Override
public void run() {
view_data.setText(incomingMessage);
}
});
} catch (IOException e) {
Log.e(TAG, "write: Error reading Input Stream. " + e.getMessage() );
break;
}
}
}
public void write(byte[] bytes) {
String text = new String(bytes, Charset.defaultCharset());
Log.d(TAG, "write: Writing to outputstream: " + text);
try {
mmOutStream.write(bytes);
} catch (IOException e) {
}
}
}
public void SendMessage(View v) {
byte[] bytes = send_data.getText().toString().getBytes(Charset.defaultCharset());
mConnectedThread.write(bytes);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
send_data =(EditText) findViewById(R.id.editText);
view_data = (TextView) findViewById(R.id.textView);
if (bluetoothAdapter != null && !bluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new
Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
}
public void Start_Server(View view) {
AcceptThread accept = new AcceptThread();
accept.start();
}
private class AcceptThread extends Thread {
private final BluetoothServerSocket mmServerSocket;
public AcceptThread(){
BluetoothServerSocket tmp = null ;
try{
tmp = bluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord("appname", MY_UUID_INSECURE);
}catch (IOException e){
}
mmServerSocket = tmp;
}
public void run(){
Log.d(TAG, "run: AcceptThread Running.");
BluetoothSocket socket = null;
try{
// This is a blocking call and will only return on a
// successful connection or an exception
socket = mmServerSocket.accept();
}catch (IOException e){
}
//talk about this is in the 3rd
if(socket != null){
connected(socket);
}
}
}
Related
Hei there,
I m trying to make an App with Android-Studio that can record sound using a Bluetooth-HS.
I know there are a lot of posts close to this, but i tried all the answers and it wont work for me.
My code gives me back a filled bytebuffer, however testing proves, its always the Phones Mic not the Headset-Mic.
If anyone could take a look at my code and point out why it wont use the BT-HS, that would be a huge help for me.
public class Inhalation extends AppCompatActivity {
AudioManager audioManager;
AudioRecord audioRecord=null;
Button mrecord;
Button mpause;
boolean isRecording=false;
private Thread recordingThread = null;
private int bufferSize = AudioRecord.getMinBufferSize(8000,AudioFormat.CHANNEL_IN_MONO,AudioFormat.ENCODING_PCM_16BIT);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_inhalation);
mrecord= findViewById(R.id.Button_Record_ID);
mpause=findViewById(R.id.Button_Pause_ID);
audioManager =(AudioManager) this.getSystemService(this.AUDIO_SERVICE);
}
//is supposed to start recording using the BT MIC. Can only be called if BTSCO is connected
private void startRecording() {
audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, 8000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize);
audioRecord.startRecording();
isRecording = true;
recordingThread = new Thread(new Runnable() {
public void run() {
writeAudioDataToFile();
}
}, "AudioRecorder Thread");
recordingThread.start();
}
//picks up the recorded audiobuffer and writes it into a file
private void writeAudioDataToFile() {
String filename="record";
byte saudioBuffer[] = new byte[bufferSize];
FileOutputStream os = null;
// TODO (4) Audiorecord Filecreation
try {
os = openFileOutput(filename, Context.MODE_PRIVATE);
} catch (FileNotFoundException e) {
e.printStackTrace();
Log.d("headset_rec","false filepath");
}
while (isRecording) {
audioRecord.read(saudioBuffer, 0, bufferSize);
try {
os.write(saudioBuffer, 0, bufferSize);
// os.write(saudioBuffer);
Log.d("headset_rec","writing"+saudioBuffer[0]);
} catch (IOException e) {
e.printStackTrace();
Log.d("headset_rec","writefail");
}
}
try {
os.close();
} catch (IOException e) {
Log.d("headset_rec","close");
e.printStackTrace();
}
}
//stops the recording
private void stopRecording() {
// stops the recording activity
if (null != audioRecord) {
isRecording = false;
audioRecord.stop();
audioRecord.release();
audioRecord = null;
recordingThread = null;
}
}
public void Record_On_Click(View view){
mpause.setEnabled(true);
mrecord.setEnabled(false);
requestRecordAudioPermission();
startRecording();
}
//Button to pause
public void Record_Pause_Click(View view){
stopRecording();
// readFromFile();
mrecord.setEnabled(true);
mpause.setEnabled(false);
}
//if BluetoothSCO is connected enables recording
private BroadcastReceiver mBluetoothScoReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
System.out.println("ANDROID Audio SCO state: " + state);
if (AudioManager.SCO_AUDIO_STATE_CONNECTED == state) {
Log.d("SCOO","connected");
mrecord.setEnabled(true);
}
if(AudioManager.SCO_AUDIO_STATE_DISCONNECTED==state){
Log.d("SCOO","disconnected");
mrecord.setEnabled(false);
}
}
};
//connects to the bluetoothHeadset doing the following:
#Override
protected void onResume() {
// TODO (5) Bluetooth Mik
// Start Bluetooth SCO.
if(isRecording){
mpause.setEnabled(true);
mrecord.setEnabled(false);
}
IntentFilter intentFilter = new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
registerReceiver(mBluetoothScoReceiver, intentFilter);
audioManager.setMode(audioManager.MODE_NORMAL);
audioManager.setBluetoothScoOn(true);
audioManager.startBluetoothSco();
// Stop Speaker.
audioManager.setSpeakerphoneOn(false);
super.onResume();
}
//Disconnects from the Bluetoothheadset doing the following
#Override
protected void onDestroy() {
audioManager.stopBluetoothSco();
audioManager.setMode(audioManager.MODE_NORMAL);
audioManager.setBluetoothScoOn(false);
// Start Speaker.
audioManager.setSpeakerphoneOn(true);
unregisterReceiver(mBluetoothScoReceiver);
super.onDestroy();
}
private void requestRecordAudioPermission() {//gets the permission to record audio
//check API version, do nothing if API version < 23!
int currentapiVersion = android.os.Build.VERSION.SDK_INT;
if (currentapiVersion > android.os.Build.VERSION_CODES.LOLLIPOP){
if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
Log.d("Activity_Request", "Wastn granted!");
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.RECORD_AUDIO)) {
Log.d("Activity_Request", "request!");
// Show an expanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed, we can request the permission.
Log.d("Activity_Request", "take!");
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, 1);
}
}
}
}
I have implemented this code to get data through udp packages but I can read just the first package (Thread run() method run one time). I'm implementing a thread and a handler.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textViewState = (TextView)findViewById(R.id.state);
new Thread() {
#Override
public void run() {
byte[] buffer = new byte[100];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
DatagramSocket datagramSocket = null;
try {
datagramSocket = new DatagramSocket(3333);
} catch (SocketException e) {
e.printStackTrace();
}
try {
datagramSocket.receive(packet);
mHandler.obtainMessage(2, 10, -1, buffer)
.sendToTarget(); // Send the obtained bytes to the UI activity
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
if (msg.what == 2) {
byte[] readRpmBuf = (byte[]) msg.obj;
String val="";
for (int i=0;i<100;i++){
val+=String.valueOf(readRpmBuf[i])+"-";
}
textViewState.setText(val);
}
}
};
}
I want to write program that use one server that receive msg from reporters in specific port and send online msg to client (readers) that are connected on another specific port ...
tip1 =>
my server has two open port ... one specific for senders and another for reader...
tip2 =>
when msg is received from sender in server => we(server) should send this msg to all online client that listen
how can I implement them...
I have problem in send msg from server to "all" client!
You can do it like this -
public class SenderReceiver {
private static volatile boolean serverStarted;
private static final String SERVER_HOST = "127.0.0.1";
private static final int SERVER_PORT = 25000;
private static final List<ReceiverConnectionHandler> handlers = new CopyOnWriteArrayList<ReceiverConnectionHandler>();
private static final ExecutorService executorService = Executors.newCachedThreadPool();
public static void main(String[] args) {
// start server
executorService.submit(new SenderReceiver().new Server());
// wait until started
while (!serverStarted) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// start receiver threads
int i = 0;
while (i++ < 10) {
executorService.submit(new Receiver(SERVER_HOST, SERVER_PORT));
}
// start sender threads
i = 0;
while (i++ < 5) {
executorService.submit(new Sender(SERVER_HOST, SERVER_PORT));
}
}
private class Server implements Runnable {
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(SERVER_PORT);
serverStarted = true;
System.out.println("Server started");
while (true) {
Socket socket = serverSocket.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String connectionName = br.readLine();
if ("sender".equals(connectionName)) {
executorService.submit(new SenderConnectionHandler(br, handlers));
} else {
ReceiverConnectionHandler handler = new ReceiverConnectionHandler(socket);
handlers.add(handler);
executorService.submit(handler);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
private class SenderConnectionHandler implements Runnable {
private BufferedReader br;
private List<ReceiverConnectionHandler> handlers;
public SenderConnectionHandler(BufferedReader br, List<ReceiverConnectionHandler> handlers) {
this.br = br;
this.handlers = handlers;
}
public void run() {
try {
String message;
while ((message = br.readLine()) != null) {
Thread.sleep(1000); // just allowing all clients to be registered
for (ReceiverConnectionHandler handler : handlers) {
handler.update(message);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
private class ReceiverConnectionHandler implements Runnable {
private Socket receiverSocket;
private final BlockingQueue<String> messages = new LinkedBlockingQueue<>();
public ReceiverConnectionHandler(Socket socket) {
this.receiverSocket = socket;
}
public void run() {
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new OutputStreamWriter(receiverSocket.getOutputStream()));
String message;
while ((message = messages.poll(1, TimeUnit.SECONDS)) != null) {
bw.write(message);
bw.newLine();
bw.flush();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bw != null) {
try {
bw.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public void update(Object message) {
if (message instanceof String) {
messages.add((String) message);
}
}
}
}
class Sender implements Runnable {
private static AtomicInteger senderCount = new AtomicInteger(0);
private String serverHost;
private int serverPort;
public Sender(String serverHost, int serverPort) {
this.serverHost = serverHost;
this.serverPort = serverPort;
}
public void run() {
BufferedWriter bw = null;
try {
Socket socket = new Socket(serverHost, serverPort);
int senderNumber = senderCount.incrementAndGet();
bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write("sender");
bw.newLine();
String message = "This is a test message from sender " + senderNumber;
bw.write(message);
bw.newLine();
System.out.println("Sender " + senderNumber + " : " + message);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bw != null) {
try {
bw.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
class Receiver implements Runnable {
private static AtomicInteger receiverCount = new AtomicInteger(0);
private String serverHost;
private int serverPort;
public Receiver(String serverHost, int serverPort) {
this.serverHost = serverHost;
this.serverPort = serverPort;
}
public void run() {
BufferedReader br = null;
BufferedWriter bw = null;
try {
Socket socket = new Socket(serverHost, serverPort);
int receiverNumber = receiverCount.incrementAndGet();
bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write("client");
bw.newLine();
bw.flush();
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String message;
while ((message = br.readLine()) != null) {
System.out.println("Receiver " + receiverNumber + ": " + message);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (bw != null) {
try {
bw.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
When I attempt to connect through a socket to my Android App, I get the following error:
10-02 01: 32: 30.295 1738-1892 / me.schat E / schat / SimpleSocket: java.net.SocketTimeoutException: failed to connect to schat.me/188.40.116.82 (port 7667) after 20000ms
This error occurs only in the emulator. When i test directly on the phone it works.
Internet works on the emulator, the browser opens any website.
My socket code in its entirety
package me.schat.net;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import javax.net.SocketFactory;
import java.io.*;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
public class SimpleSocket {
private static final String TAG = "schat/SimpleSocket";
private final Object m_sendLock = new Object();
private boolean m_authorized = false; // true после успешной авторизации.
private DataInputStream m_in; // Поток чтения транспортных пакетов.
private DataOutputStream m_out; // Поток записи транспортных пакетов.
private Handler m_handler; // Объект доступа к потоку отправки пакетов.
private int m_reconnects = 0; // Число попыток восстановить соединение.
private long m_rxSequence = 0; // Счётчик полученных пакетов.
private long m_txSequence = 0; // Счётчик отправленных пакетов.
private Network network; // Информация для подключения.
private PacketListener m_packets; // Слушатель пакетов.
private Socket m_socket; // Сокет подключения.
private SocketListener m_listener; // Слушатель сокета.
private Thread m_thread; // Поток чтения пакетов.
private Timer m_timer; // Таймер обслуживающий соединение.
private TimerTask m_killTask; // Задача для отключения от сервера, если он не ответил за определённое время.
private TransportReader m_reader; // Объект чтения транспортных пакетов.
private ByteArrayOutputStream m_send = new ByteArrayOutputStream(); // Поток отправки пакетов.
public SimpleSocket(SocketListener listener, PacketListener packets) {
m_listener = listener;
m_packets = packets;
m_reader = new TransportReader(this);
m_timer = new Timer("SocketTimer");
HandlerThread thread = new HandlerThread("simplesocket-thread");
thread.start();
m_handler = new Handler(thread.getLooper());
}
public boolean connect(Network network) {
this.network = network;
return connect();
}
public boolean connect() {
Log.d(TAG, "connect()");
if ((m_thread != null && m_thread.isAlive()) || network == null)
return false;
m_thread = new Thread(new Runnable() {
public void run() {
Log.d(TAG, "RUN " + Thread.currentThread().getId());
int port = network.uri.getPort();
if (port == -1)
port = Protocol.DEFAULT_PORT;
try {
SocketAddress sockaddr = new InetSocketAddress(network.uri.getHost(), port);
SocketFactory factory = SocketFactory.getDefault();
m_socket = factory.createSocket();
m_socket.setTcpNoDelay(true);
m_socket.setKeepAlive(true);
m_socket.connect(sockaddr, Protocol.CONNECT_TIMEOUT);
m_in = new DataInputStream(new BufferedInputStream(m_socket.getInputStream()));
m_out = new DataOutputStream(new BufferedOutputStream(m_socket.getOutputStream()));
} catch (IOException ioe) {
Log.e(TAG, ioe.toString());
reconnect();
return;
}
catch (NullPointerException npe) {
Log.e(TAG, npe.toString());
reconnect();
return;
}
ping();
m_reconnects = 0;
m_listener.onConnect();
m_listener.onAuthRequired();
try {
m_reader.start(m_in);
} catch (IOException ioe) {
Log.e(TAG, "Socket read exception", ioe);
reconnect();
}
}
});
m_thread.start();
return true;
}
public boolean send(final WritablePacket packet) {
List<WritablePacket> packets = new ArrayList<WritablePacket>();
packets.add(packet);
return send(packets);
}
public boolean send(final List<WritablePacket> packets) {
if (packets.isEmpty())
return false;
m_handler.post(new Runnable() {
public void run() {
synchronized (m_sendLock) {
try {
List<byte[]> raws = new ArrayList<byte[]>(packets.size());
int options = Protocol.NO_OPTIONS;
for (WritablePacket packet : packets) {
final byte[] raw = packet.write(m_send).toByteArray();
raws.add(raw);
if (raw.length > 65535)
options = Protocol.HUGE_PACKETS;
}
new TransportWriter(m_out, raws, m_txSequence, options);
m_txSequence++;
} catch (IOException ioe) {
Log.e(TAG, "Send failed", ioe);
}
}
}
});
return true;
}
public final Network getNetwork() {
return network;
}
public final PacketListener packets() {
return m_packets;
}
public final synchronized boolean isAuthorized() {
return m_authorized;
}
public final synchronized void setAuthorized(boolean authorized) {
m_authorized = authorized;
}
public final void leave() {
m_reconnects = -1;
disconnect();
}
/**
* Отключение от сервера.
*/
public final void disconnect() {
if (m_socket == null)
return;
m_handler.post(new Runnable() {
public void run() {
try {
if (m_socket != null) {
m_socket.close();
m_socket = null;
}
} catch (IOException ioe) {
Log.e(TAG, "Error while disconnecting", ioe);
}
if (m_thread != null) {
m_thread.interrupt();
m_thread = null;
}
}
});
}
public final void ping() {
if (m_killTask != null)
m_killTask.cancel();
m_timer.schedule(new TimerTask() {
public void run() {
if (isAuthorized()) {
transmit(new byte[0], Protocol.INTERNAL_PACKET);
m_killTask = new TimerTask() {
public void run() {
disconnect();
}
};
m_timer.schedule(m_killTask, Protocol.REPLY_TIMEOUT);
} else
disconnect();
}
}, Protocol.IDLE_TIMEOUT);
}
private void reconnect() {
if (m_thread != null) {
m_thread.interrupt();
m_thread = null;
}
if (m_reconnects == -1)
return;
if (m_reconnects >= Protocol.MAX_FAST_RECONNECTS + Protocol.MAX_NORMAL_RECONNECTS)
m_reconnects = 0;
++m_reconnects;
m_timer.schedule(new TimerTask() {
public void run() {
connect();
}
}, m_reconnects <= Protocol.MAX_FAST_RECONNECTS ? Protocol.FAST_RECONNECT_TIME : Protocol.NORMAL_RECONNECT_TIME);
m_listener.onReconnect();
}
private boolean transmit(final byte[] packet, final int options) {
List<byte[]> packets = new ArrayList<byte[]>();
packets.add(packet);
return transmit(packets, options);
}
private boolean transmit(final List<byte[]> packets, final int options) {
// Log.d(TAG, "transmit(List<byte[]> packets)");
if (packets.isEmpty())
return false;
m_handler.post(new Runnable() {
public void run() {
synchronized (m_sendLock) {
try {
new TransportWriter(m_out, packets, m_txSequence, options);
if (options != Protocol.INTERNAL_PACKET)
m_txSequence++;
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
return false;
}
}
I've spent long on this but no success yet. In my application to capture image and send to the server, I get NullPointerException below;
java.lang.NullPointerException: 0
at Files.CameraMIDlet.snap(CameraMIDlet.java:120)
at Files.CameraForm.commandAction(CameraForm.java:116)
at javax.microedition.lcdui.Display$ChameleonTunnel.callScreenListener(), bci=46
at com.sun.midp.chameleon.layers.SoftButtonLayer.processCommand(), bci=74
at com.sun.midp.chameleon.layers.SoftButtonLayer.soft2(), bci=173
at com.sun.midp.chameleon.layers.SoftButtonLayer.keyInput(), bci=78
at com.sun.midp.chameleon.CWindow.keyInput(), bci=38
at javax.microedition.lcdui.Display$DisplayEventConsumerImpl.handleKeyEvent(), bci=17
at com.sun.midp.lcdui.DisplayEventListener.process(), bci=277
at com.sun.midp.events.EventQueue.run(), bci=179
at java.lang.Thread.run(Thread.java:722)
The errors happen at byte[] image = videoControl.getSnapshot("encoding = jpeg"); in the CameraMIDlet and also at midlet.snap(); in the CameraForm, in the code below.
The code for CameraForm is here:
package Files;
import javax.microedition.media.*;
import javax.microedition.lcdui.*;
import javax.microedition.media.control.*;
import java.io.IOException;
class CameraForm extends Form implements CommandListener {
private final CameraMIDlet midlet;
private final Command exitCommand;
private Command captureCommand = null;
private Command showImageCommand = null;
private Player player = null;
private static VideoControl videoControl = null;
private boolean active = false;
private StringItem messageItem;
public CameraForm(CameraMIDlet midlet) {
super("Camera");
this.midlet = midlet;
messageItem = new StringItem("Message", "start");
append(messageItem);
exitCommand = new Command("EXIT", Command.EXIT, 1);
addCommand(exitCommand);
setCommandListener(this);
try {
//creates a new player and set it to realize
player = Manager.createPlayer("capture://video");
player.realize();
//Grap the Video control and set it to the current display
videoControl = (VideoControl) (player.getControl("VideoControl"));
if (videoControl != null) {
append((Item) (videoControl.initDisplayMode(
VideoControl.USE_GUI_PRIMITIVE, null)));
captureCommand = new Command("CAPTURE", Command.SCREEN, 1);
addCommand(captureCommand);
messageItem.setText("OK");
} else {
messageItem.setText("No video control");
}
} catch (IOException ioe) {
messageItem.setText("IOException: " + ioe.getMessage());
} catch (MediaException me) {
messageItem.setText("Media Exception: " + me.getMessage());
} catch (SecurityException se) {
messageItem.setText("Security Exception: " + se.getMessage());
}
}
* the video should be visualized on the sreen
* therefore you have to start the player and set the videoControl visible
synchronized void start() {
if (!active) {
try {
if (player != null) {
player.start();
}
if (videoControl != null) {
videoControl.setVisible(true);
//midlet.snap();
}
} catch (MediaException me) {
messageItem.setText("Media Exception: " + me.getMessage());
} catch (SecurityException se) {
messageItem.setText("Security Exception: " + se.getMessage());
}
active = true;
}
}
* to stop the player. First the videoControl has to be set invisible
* than the player can be stopped
synchronized void stop() {
if (active) {
try {
if (videoControl != null) {
videoControl.setVisible(false);
}
if (player != null) {
player.stop();
}
} catch (MediaException me) {
messageItem.setText("Media Exception: " + me.getMessage());
}
active = false;
}
}
* on the captureCommand a picture is taken and transmited to the server
public void commandAction(Command c, Displayable d) {
if (c == exitCommand) {
midlet.cameraFormExit();
} else {
if (c == captureCommand) {
midlet.snap();
}
}
}
}
The code for CameraMIDlet is below:
package Files;
import java.io.*;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.io.*;
import javax.microedition.media.control.*;
import java.io.IOException;
import javax.microedition.media.MediaException;
public class CameraMIDlet extends MIDlet {
private CameraForm cameraSave = null;
private DisplayImage displayImage = null;
CameraForm captureThread;
private static VideoControl videoControl;
private StringItem messageItem;
public CameraMIDlet() {
}
/*
* startApp()
* starts the MIDlet and generates cameraSave, displayImage, database
*
**/
public void startApp() {
Displayable current = Display.getDisplay(this).getCurrent();
if (current == null) {
//first call
cameraSave = new CameraForm(this);
displayImage = new DisplayImage(this);
Display.getDisplay(this).setCurrent(cameraSave);
cameraSave.start();
} else {
//returning from pauseApp
if (current == cameraSave) {
cameraSave.start();
}
Display.getDisplay(this).setCurrent(current);
}
}
public void pauseApp() {
if (Display.getDisplay(this).getCurrent() == cameraSave) {
cameraSave.stop();
}
}
public void destroyApp(boolean unconditional) {
if (Display.getDisplay(this).getCurrent() == cameraSave) {
cameraSave.stop();
}
}
private void exitRequested() {
destroyApp(false);
notifyDestroyed();
}
void cameraFormExit() {
exitRequested();
}
/**
* restart the camera again
*
*/
void displayCanvasBack() {
Display.getDisplay(this).setCurrent(cameraSave);
cameraSave.start();
}
/**
* the byte[] of the image should be transmitted to a server
*
**/
void buildHTTPConnection(byte[] byteImage) {
displayImage.setImage(byteImage);
Display.getDisplay(this).setCurrent(displayImage);
HttpConnection hc = null;
OutputStream out = null;
try {
//enode the image data by the Base64 algorithm
String stringImage = Base64.encode(byteImage);
// URL of the Sevlet
String url = new String(
"http://ip-adress:8080/C:/Users/HASENDE/Documents/NetBeansProjects/Mobile/pics");
// Obtain an HTTPConnection
hc = (HttpConnection) Connector.open(url);
// Modifying the headers of the request
hc.setRequestMethod(HttpConnection.POST);
// Obtain the output stream for the HttpConnection
out = hc.openOutputStream();
out.write(stringImage.getBytes());
} catch (IOException ioe) {
StringItem stringItem = new StringItem(null, ioe.toString());
} finally {
try {
if (out != null)
out.close();
if (hc != null)
hc.close();
} catch (IOException ioe) {
}
}
// ** end network
}
/**
* stop the camera, show the captured image and transmit the image to a server
**/
void transmitImage(byte[] image) {
cameraSave.stop();
Display.getDisplay(this).setCurrent(displayImage);
buildHTTPConnection(image);
}
public void snap(){
try {
byte[] image = videoControl.getSnapshot("encoding = jpeg");
transmitImage(image);
messageItem.setText("Ok");
} catch (MediaException me) {
messageItem.setText("Media Exception: " + me.getMessage());
}
}
}
By identifying the statement that throws NPE you get 99% close to finding the bug:
byte[] image = videoControl.getSnapshot("encoding = jpeg");
NPE in above statement means videoControl is null. Now if you look at it closer, you may notice that in CameraMIDlet, videoControl is initialized with null and never changes to anything else - that's why you are getting NPE. By the way, from CameraForm code it looks like you intended to use videoControl object that is defined there, didn't you.
Side note. CameraForm seems to be designed to used in multiple threads (there are synchronized modifiers) - if this is the case, you better make sure that videoControl is also obtained from it in a synchronized way. Also in that case, add volatile modifier in definition of active flag:
private volatile boolean active = false; // in CameraForm
For Capturing photo use canvas instead of Form,
Check follwing code for Photo Capture
public class ImageCaptureCanvas extends Canvas {
UrMidlet midlet;
VideoControl videoControl;
Player player;
SnapShotCanvas snap;
private Display display;
public ImageCaptureCanvas(UrMidlet midlet) throws MediaException {
this.midlet = midlet;
this.display = Display.getDisplay(midlet);
this.setFullScreenMode(true);
try {
player = Manager.createPlayer("capture://image");
player.realize();
videoControl = (VideoControl) player.getControl("VideoControl");
} catch (Exception e) {
dm(e.getClass().getName());
}
videoControl.initDisplayMode(VideoControl.USE_DIRECT_VIDEO, this);
try {
videoControl.setDisplayLocation(0,0);
videoControl.setDisplaySize(getWidth(), getHeight());
} catch (MediaException me) {
try {
videoControl.setDisplayFullScreen(true);
} catch (MediaException me2) {
}
}
dm("icc10");
videoControl.setVisible(true);
dm("icc11");
player.start();
this.display.setCurrent(this);
}
public void dm(String message) {
Form form = new Form("Error");
form.append(message);
display.setCurrent(form);
}
public void paint(Graphics g) {
}
protected void keyPressed(int keyCode) {
boolean prv=false;
int actn=getGameAction(keyCode);
switch (keyCode) {
case KEY_NUM5:
prv=true;
Thread t = new Thread() {
public void run() {
try {
byte[] raw = videoControl.getSnapshot(null);
Image image = Image.createImage(raw, 0, raw.length);
snap = new SnapShotCanvas(image);
display.setCurrent(snap);
} catch (Exception e) {
dm(e.getClass().getName() + " " + e.getMessage());
}
}
};
t.start();
break;
}
if(!prv){
switch (actn) {
case Canvas.FIRE:
Thread t1 = new Thread() {
public void run() {
try {
byte[] raw = videoControl.getSnapshot(null);
Image image = Image.createImage(raw, 0, raw.length);
snap = new SnapShotCanvas(image);
display.setCurrent(snap);
} catch (Exception e) {
dm(e.getClass().getName() + " " + e.getMessage());
}
}
};
t1.start();
break;
}
}
}
}
SnapShotCanvas Code here
class SnapShotCanvas extends Canvas {
private Image image;
public SnapShotCanvas(Image image) {
this.image = image;
setFullScreenMode(true);
}
public void paint(Graphics g) {
g.drawImage(image, getWidth() / 2, getHeight() / 2, Graphics.HCENTER | Graphics.VCENTER);
}
}