I want to get the audio from Bluetooth headset and play it on Bluetooth headset itself. I am able to do that on lollipop(5.1.1)(Samsung note 3 neo) but it is not working on android(7.0)(Redmi Note 4).
I am first creating an audio track and then start a new thread for reading audio from mic. First, it starts reading audio from phonemic. After clicking the Bluetooth button it starts Bluetooth SCO.
Can anyone help?
package surya.com.audiorecord;
import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import java.nio.ByteBuffer;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Sample that demonstrates how to record from a Bluetooth HFP microphone using {#link AudioRecord}.
*/
public class BluetoothRecordActivity extends AppCompatActivity {
private static final String TAG = BluetoothRecordActivity.class.getCanonicalName();
private static final int SAMPLING_RATE_IN_HZ = 16000;
private static final int CHANNEL_CONFIG = AudioFormat.CHANNEL_IN_MONO;
private static final int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
/**
* Factor by that the minimum buffer size is multiplied. The bigger the factor is the less
* likely it is that samples will be dropped, but more memory will be used. The minimum buffer
* size is determined by {#link AudioRecord#getMinBufferSize(int, int, int)} and depends on the
* recording settings.
*/
private static final int BUFFER_SIZE_FACTOR = 2;
/**
* Size of the buffer where the audio data is stored by Android
*/
private static final int BUFFER_SIZE = AudioRecord.getMinBufferSize(SAMPLING_RATE_IN_HZ,
CHANNEL_CONFIG, AUDIO_FORMAT) * BUFFER_SIZE_FACTOR;
/**
* Signals whether a recording is in progress (true) or not (false).
*/
private final AtomicBoolean recordingInProgress = new AtomicBoolean(false);
private AudioRecord recorder = null;
private AudioManager audioManager;
private Thread recordingThread = null;
private Button startButton;
private Button stopButton;
private Button bluetoothButton;
AudioTrack mAudioTrack;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.bluetooth);
audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
try {
outputBufferSize = AudioTrack.getMinBufferSize(16000,
AudioFormat.CHANNEL_IN_STEREO,
AudioFormat.ENCODING_PCM_16BIT);
mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 16000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, outputBufferSize, AudioTrack.MODE_STREAM);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mAudioTrack.setVolume(100);
}
mAudioTrack.play();
} catch (Exception e) {
e.printStackTrace();
}
startButton = (Button) findViewById(R.id.btnStart);
startButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startRecording();
}
});
stopButton = (Button) findViewById(R.id.btnStop);
stopButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
stopRecording();
}
});
bluetoothButton = (Button) findViewById(R.id.btnBluetooth);
bluetoothButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
activateBluetoothSco();
}
});
requestAudioPermissions();
}
int outputBufferSize;
#Override
protected void onResume() {
super.onResume();
ButtonEnableSetters();
registerReceiver(bluetoothStateReceiver, new IntentFilter(
AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED));
}
private void ButtonEnableSetters() {
runOnUiThread(new Runnable() {
#Override
public void run() {
bluetoothButton.setEnabled(calculateBluetoothButtonState());
startButton.setEnabled(calculateStartRecordButtonState());
stopButton.setEnabled(calculateStopRecordButtonState());
}
});
}
#Override
protected void onPause() {
super.onPause();
stopRecording();
unregisterReceiver(bluetoothStateReceiver);
}
private void startRecording() {
// Depending on the device one might has to change the AudioSource, e.g. to DEFAULT
// or VOICE_COMMUNICATION
recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
SAMPLING_RATE_IN_HZ, CHANNEL_CONFIG, AUDIO_FORMAT, BUFFER_SIZE);
recorder.startRecording();
recordingInProgress.set(true);
try {
recordingThread = new Thread(new RecordingRunnable(), "Recording Thread");
recordingThread.start();
} catch (Exception e) {
e.printStackTrace();
}
ButtonEnableSetters();
}
private void stopRecording() {
if (null == recorder) {
return;
}
recordingInProgress.set(false);
recorder.stop();
recorder.release();
recorder = null;
recordingThread = null;
ButtonEnableSetters();
}
private void activateBluetoothSco() {
if (!audioManager.isBluetoothScoAvailableOffCall()) {
Log.e(TAG, "SCO ist not available, recording is not possible");
return;
}
if (!audioManager.isBluetoothScoOn()) {
audioManager.startBluetoothSco();
audioManager.setBluetoothScoOn(true);
}
}
private void bluetoothStateChanged(BluetoothState state) {
Log.i(TAG, "Bluetooth state changed to:" + state);
if (BluetoothState.UNAVAILABLE == state && recordingInProgress.get()) {
stopRecording();
}
ButtonEnableSetters();
}
private boolean calculateBluetoothButtonState() {
return !audioManager.isBluetoothScoOn();
}
private boolean calculateStartRecordButtonState() {
return audioManager.isBluetoothScoOn() && !recordingInProgress.get();
}
private boolean calculateStopRecordButtonState() {
return audioManager.isBluetoothScoOn() && recordingInProgress.get();
}
private class RecordingRunnable implements Runnable {
#Override
public void run() {
if (mAudioTrack != null) {
if (mAudioTrack.getPlayState() != AudioTrack.PLAYSTATE_PLAYING) {
mAudioTrack.play();
} else {
mAudioTrack.stop();
mAudioTrack.flush();
mAudioTrack.play();
}
}
// final File file = new File(Environment.getExternalStorageDirectory(), "recording.pcm");
final ByteBuffer buffer = ByteBuffer.allocateDirect(BUFFER_SIZE);
while (recordingInProgress.get()) {
int result = recorder.read(buffer, BUFFER_SIZE);
if (result 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay!
// recordAudio();
activateBluetoothSco();
startRecording();
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
Toast.makeText(this, "Permissions Denied to record audio", Toast.LENGTH_LONG).show();
}
return;
}
}
}
private final BroadcastReceiver bluetoothStateReceiver = new BroadcastReceiver() {
private BluetoothState bluetoothState = BluetoothState.UNAVAILABLE;
#Override
public void onReceive(Context context, Intent intent) {
int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
switch (state) {
case AudioManager.SCO_AUDIO_STATE_CONNECTED:
Log.i(TAG, "Bluetooth HFP Headset is connected");
handleBluetoothStateChange(BluetoothState.AVAILABLE);
break;
case AudioManager.SCO_AUDIO_STATE_CONNECTING:
Log.i(TAG, "Bluetooth HFP Headset is connecting");
handleBluetoothStateChange(BluetoothState.UNAVAILABLE);
case AudioManager.SCO_AUDIO_STATE_DISCONNECTED:
Log.i(TAG, "Bluetooth HFP Headset is disconnected");
handleBluetoothStateChange(BluetoothState.UNAVAILABLE);
break;
case AudioManager.SCO_AUDIO_STATE_ERROR:
Log.i(TAG, "Bluetooth HFP Headset is in error state");
handleBluetoothStateChange(BluetoothState.UNAVAILABLE);
break;
}
}
private void handleBluetoothStateChange(BluetoothState state) {
if (bluetoothState == state) {
return;
}
bluetoothState = state;
bluetoothStateChanged(state);
}
};
}
This is the project source code
https://bitbucket.org/surya945/audiorecord
welcome to stackoverflow
I think your issue related to
TargetSdkVersion in build.gardle(module:app)
check this
Related
I am writing a Android program that Streams MIC directly to Speaker of Phone.The code works but UI hangs and app hangs.But Still audio transfer is working even if the app hangs.Where is the error..?
RecordBufferSize=AudioRecord.getMinBufferSize(sampleRateInHz,AudioFormat.CHANNEL_IN_MONO,AudioFormat.ENCODING_PCM_16BIT);
TrackBufferSize= AudioTrack.getMinBufferSize(sampleRateInHz,AudioFormat.CHANNEL_OUT_MONO,AudioFormat.ENCODING_PCM_16BIT);
am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
Record record = new Record();
record.run();
}
public class Record extends Thread
{
final short[] buffer = new short[RecordBufferSize];
short[] readBuffer = new short[TrackBufferSize];
public void run() {
isRecording = true;
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
AudioRecord arec = new AudioRecord(MediaRecorder.AudioSource.MIC,sampleRateInHz,AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT,RecordBufferSize);
AudioTrack atrack = new AudioTrack(AudioManager.STREAM_MUSIC,sampleRateInHz,AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, TrackBufferSize, AudioTrack.MODE_STREAM);
//am.setRouting(AudioManager.MODE_NORMAL, AudioManager.ROUTE_EARPIECE, AudioManager.ROUTE_ALL);
atrack.setPlaybackRate(sampleRateInHz);
byte[] buffer = new byte[RecordBufferSize];
arec.startRecording();
atrack.play();
while(isRecording) {
AudioLenght=arec.read(buffer, 0, RecordBufferSize);
atrack.write(buffer, 0, AudioLenght);
}
arec.stop();
atrack.stop();
isRecording = false;
}
}
This is my code.
I tried this and got result.Try this
Java Code I used:-
package com.example.root.akuvo;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.PorterDuff;
import android.media.AudioAttributes;
import android.media.AudioDeviceInfo;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaRecorder;
import android.media.audiofx.AcousticEchoCanceler;
import android.media.audiofx.AutomaticGainControl;
import android.media.audiofx.BassBoost;
import android.media.audiofx.NoiseSuppressor;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
public class MicToSpeakerActivity extends AppCompatActivity {
//Audio
private Button mOn;
private boolean isOn;
private boolean isRecording;
private AudioRecord record;
private AudioTrack player;
private AudioManager manager;
private int recordState, playerState;
private int minBuffer;
//Audio Settings
private final int source = MediaRecorder.AudioSource.CAMCORDER;
private final int channel_in = AudioFormat.CHANNEL_IN_MONO;
private final int channel_out = AudioFormat.CHANNEL_OUT_MONO;
private final int format = AudioFormat.ENCODING_PCM_16BIT;
private final static int REQUEST_ENABLE_BT = 1;
private boolean IS_HEADPHONE_AVAILBLE=false;
#RequiresApi(api = Build.VERSION_CODES.M)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mic_to_speaker);
//Reduce latancy
setVolumeControlStream(AudioManager.MODE_IN_COMMUNICATION);
mOn = (Button) findViewById(R.id.button);
isOn = false;
isRecording = false;
manager = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
manager.setMode(AudioManager.MODE_IN_COMMUNICATION);
//Check for headset availability
AudioDeviceInfo[] audioDevices = manager.getDevices(AudioManager.GET_DEVICES_ALL);
for(AudioDeviceInfo deviceInfo : audioDevices) {
if (deviceInfo.getType() == AudioDeviceInfo.TYPE_WIRED_HEADPHONES || deviceInfo.getType() == AudioDeviceInfo.TYPE_WIRED_HEADSET || deviceInfo.getType() == AudioDeviceInfo.TYPE_USB_HEADSET) {
IS_HEADPHONE_AVAILBLE = true;
}
}
if (!IS_HEADPHONE_AVAILBLE){
// get delete_audio_dialog.xml view
LayoutInflater layoutInflater = LayoutInflater.from(MicToSpeakerActivity.this);
View promptView = layoutInflater.inflate(R.layout.insert_headphone_dialog, null);
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(MicToSpeakerActivity.this);
alertDialogBuilder.setView(promptView);
// setup a dialog window
alertDialogBuilder.setCancelable(false)
.setPositiveButton("Try Again", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
startActivity(new Intent(getIntent()));
}
})
.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
startActivity(new Intent(MicToSpeakerActivity.this,MainActivity.class));
dialog.cancel();
}
});
// create an alert dialog
AlertDialog alert = alertDialogBuilder.create();
alert.show();
}
initAudio();
mOn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mOn.getBackground().setColorFilter(getResources().getColor(!isOn ? R.color.colorOn : R.color.colorOff), PorterDuff.Mode.SRC_ATOP);
isOn = !isOn;
if(isOn) {
(new Thread() {
#Override
public void run()
{
startAudio();
}
}).start();
} else {
endAudio();
}
}
});
}
public void initAudio() {
//Tests all sample rates before selecting one that works
int sample_rate = getSampleRate();
minBuffer = AudioRecord.getMinBufferSize(sample_rate, channel_in, format);
record = new AudioRecord(source, sample_rate, channel_in, format, minBuffer);
recordState = record.getState();
int id = record.getAudioSessionId();
Log.d("Record", "ID: " + id);
playerState = 0;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
player = new AudioTrack(
new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build(),
new AudioFormat.Builder().setEncoding(format).setSampleRate(sample_rate).setChannelMask(channel_out).build(),
minBuffer,
AudioTrack.MODE_STREAM,
AudioManager.AUDIO_SESSION_ID_GENERATE);
playerState = player.getState();
// Formatting Audio
if(AcousticEchoCanceler.isAvailable()) {
AcousticEchoCanceler echo = AcousticEchoCanceler.create(id);
echo.setEnabled(true);
Log.d("Echo", "Off");
}
if(NoiseSuppressor.isAvailable()) {
NoiseSuppressor noise = NoiseSuppressor.create(id);
noise.setEnabled(true);
Log.d("Noise", "Off");
}
if(AutomaticGainControl.isAvailable()) {
AutomaticGainControl gain = AutomaticGainControl.create(id);
gain.setEnabled(false);
Log.d("Gain", "Off");
}
BassBoost base = new BassBoost(1, player.getAudioSessionId());
base.setStrength((short) 1000);
}
}
public void startAudio() {
int read = 0, write = 0;
if(recordState == AudioRecord.STATE_INITIALIZED && playerState == AudioTrack.STATE_INITIALIZED) {
record.startRecording();
player.play();
isRecording = true;
Log.d("Record", "Recording...");
}
while(isRecording) {
short[] audioData = new short[minBuffer];
if(record != null)
read = record.read(audioData, 0, minBuffer);
else
break;
Log.d("Record", "Read: " + read);
if(player != null)
write = player.write(audioData, 0, read);
else
break;
Log.d("Record", "Write: " + write);
}
}
public void endAudio() {
if(record != null) {
if(record.getRecordingState() == AudioRecord.RECORDSTATE_RECORDING)
record.stop();
isRecording = false;
Log.d("Record", "Stopping...");
}
if(player != null) {
if(player.getPlayState() == AudioTrack.PLAYSTATE_PLAYING)
player.stop();
isRecording = false;
Log.d("Player", "Stopping...");
}
}
public int getSampleRate() {
//Find a sample rate that works with the device
for (int rate : new int[] {8000, 11025, 16000, 22050, 44100, 48000}) {
int buffer = AudioRecord.getMinBufferSize(rate, channel_in, format);
if (buffer > 0)
return rate;
}
return -1;
}
}
XML Code I Used :
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.root.akuvo.MicToSpeakerActivity">
<Button
android:id="#+id/button"
android:layout_width="104dp"
android:layout_height="102dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:background="#android:drawable/ic_lock_power_off"
android:backgroundTint="#color/colorOff"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.396" />
</android.support.constraint.ConstraintLayout>
I want to check whether a headset has a microphone or not. Currently I'm using this broadcast receiver code, but I'm not sure whether it is correct or not.
public class HeadSetMicrophoneStateReceiver extends BroadcastReceiver {
private String pluggedState = null;
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_HEADSET_PLUG)) {
int state = intent.getIntExtra("microphone", -1);
switch (state) {
case 0:
//Headset does not have a Microphone
pluggedState = "0";
break;
case 1:
//Headset have a Microphone
pluggedState = "1";
break;
default:
pluggedState = "I have no idea what the headset state is";
}
EventBus.getDefault().post(new HeadSetMicrophoneEvent(pluggedState));
}
}
}
Please help me out.
This method returns whether the microphone is available.
If it is not available then an exception will be caught.
public static boolean getMicrophoneAvailable(Context context) {
MediaRecorder recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
recorder.setOutputFile(new File(context.getCacheDir(), "MediaUtil#micAvailTestFile").getAbsolutePath());
boolean available = true;
try {
recorder.prepare();
}
catch (IOException exception) {
available = false;
}
recorder.release();
return available;
}
try Following code
ackage com.example.headsetplugtest;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
public class MyActivity extends Activity {
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (Intent.ACTION_HEADSET_PLUG.equals(action)) {
Log.d("MyActivity ", "state: " + intent.getIntExtra("state", -1));
Log.d("MyActivity ", "microphone: " + intent.getIntExtra("microphone", -1));
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
getApplicationContext().registerReceiver(mReceiver, filter);
}
#Override
protected void onStop() {
super.onStop();
getApplicationContext().unregisterReceiver(mReceiver);
}
}
I am implementing a simple app that sends and receives data between two devices via bluetooth.
I am following the android developer's blog's bluetoothchat example, but my application seems unable to read from the inputstream of a socket.
Writing to the socket is fine. The app does not throw an error nor update the textview as it is supposed to. Any help would be appreciated. Thank you!
Main activity.java(where list of devices are shown and selected) - probably not the errored file:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.bluetooth.*;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Set;
import java.util.UUID;
public class MainActivity extends ActionBarActivity {
private final static int REQUEST_ENABLE_BT = 22;
private static final UUID MY_UUID = UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
private static final String NAME = "Bluetooth!";
ListView listView;
ArrayList<BluetoothDevice> deviceList;
ArrayAdapter<String> arrayAdapter;
ScanReciever reciever;
BluetoothAdapter bluetooth_adapter;
Button onButton;
Button scanButton;
Button alreadyButton;
AcceptThread acceptThread;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
deviceList = new ArrayList<>();
//arrayAdapter = new ArrayAdapter<>(this, R.xml.table_item, android.R.id.text1, deviceList);
arrayAdapter = new ArrayAdapter<String>(this, R.layout.table_item);
// Set up Buttons
onButton = (Button) findViewById(R.id.onButton);
scanButton = (Button) findViewById(R.id.scanButton);
onButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
askAdapterOn();
}
});
scanButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
scanForDevices();
}
});
// Set up listview
listView = (ListView) findViewById(R.id.listView);
listView.setAdapter(arrayAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View v, int position, long id) {
callButtons(deviceList.get(position));
}
});
// Bluetooth setup.
bluetooth_adapter = BluetoothAdapter.getDefaultAdapter();
// If device is incapable of using bluetooth:
if (bluetooth_adapter == null) {
onButton.setEnabled(false);
scanButton.setEnabled(false);
}
else if (!bluetooth_adapter.isEnabled()) { // If bluetooth is off:
//Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
//startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
onButton.setEnabled(true);
scanButton.setEnabled(false);
}
else { // Bluetooth is on and ready:
onButton.setEnabled(false);
scanButton.setEnabled(true);
alreadyButton = (Button) findViewById(R.id.alreadyButton);
alreadyButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Collect current devices into a set.
Set<BluetoothDevice> pairedDevices = bluetooth_adapter.getBondedDevices();
// Pass the index of the paired device
if (pairedDevices.size() > 0) {
callButtons(pairedDevices.iterator().next()); // First element in set.
} else {
System.out.println("No paired Device!");
}
}
});
acceptThread = new AcceptThread();
acceptThread.start();
}
}
private class ScanReciever extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
System.out.println("Started");
//discovery starts, we can show progress dialog or perform other tasks
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
System.out.println("finished");
//discovery finishes, dismis progress dialog
} else if (BluetoothDevice.ACTION_FOUND.equals(action)) {
//bluetooth device found
BluetoothDevice device = (BluetoothDevice) intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
System.out.println("FOUND: " + device.getName());
deviceList.add(device);
arrayAdapter.add(device.getName()+" - Click to pair");
arrayAdapter.notifyDataSetChanged();
} else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
System.out.println("Connected~!!!!!!!!!!!!!!");
callButtons(deviceList.get(deviceList.size()-1));
}
}
};
protected void askAdapterOn() {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
protected void scanForDevices() {
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
reciever = new ScanReciever();
registerReceiver(reciever, filter);
bluetooth_adapter.startDiscovery();
}
protected void callButtons(BluetoothDevice bd) {
bluetooth_adapter.cancelDiscovery();
Intent toButton = new Intent(getApplicationContext(), buttons.class);
toButton.putExtra("selected",bd);
startActivity(toButton);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_ENABLE_BT) {
if (resultCode == RESULT_OK){
if (bluetooth_adapter.isEnabled()){
onButton.setEnabled(false);
scanButton.setEnabled(true);
}
else {
onButton.setEnabled(true);
scanButton.setEnabled(false);
}
}
}
}
#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);
}
#Override
public void onDestroy() {
unregisterReceiver(reciever);
super.onDestroy();
}
private class AcceptThread extends Thread {
private final BluetoothServerSocket mmServerSocket;
public AcceptThread() {
// Use a temporary object that is later assigned to mmServerSocket,
// because mmServerSocket is final
BluetoothServerSocket tmp = null;
try {
// MY_UUID is the app's UUID string, also used by the client code
tmp = bluetooth_adapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
System.out.println("READY TO ACCEPT");
} catch (IOException e) { }
mmServerSocket = tmp;
}
public void run() {
BluetoothSocket socket = null;
// Keep listening until exception occurs or a socket is returned
while (true) {
try {
socket = mmServerSocket.accept();
} catch (IOException e) {
break;
}
// If a connection was accepted
if (socket != null) {
// Do work to manage the connection (in a separate thread)
//manageConnectedSocket(socket);
try {
mmServerSocket.close();
} catch (IOException e) { }
break;
}
}
}
/** Will cancel the listening socket, and cause the thread to finish */
public void cancel() {
try {
mmServerSocket.close();
} catch (IOException e) { }
}
}
}
Buttons.java(where the app will initiate a connection and maintain communication) - probably the file with the error:
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.UUID;
public class buttons extends Activity {
public static final int MESSAGE_READ = 2;
public static final int MESSAGE_WRITE = 3;
BluetoothDevice selected;
BluetoothAdapter bluetoothAdapter;
TextView tv;
Button button1;
Button button2;
Button button3;
Button unpairB;
private static final UUID MY_UUID = UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
ConnectThread connectThread;
ConnectedThread connectedThread;
BluetoothSocket mmSocket;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.buttons);
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
selected = getIntent().getExtras().getParcelable("selected");
pair(selected);
connectedThread = null;
try {
connectedThread = new ConnectedThread(mmSocket);
connectedThread.start();
System.out.println("ConnectedThread started!");
} catch (Exception e) {
Log.e("unpair()", e.getMessage());
}
// Set up Buttons
button1 = (Button) findViewById(R.id.button1);
button2 = (Button) findViewById(R.id.button2);
button3 = (Button) findViewById(R.id.button3);
unpairB = (Button) findViewById(R.id.unpairButton);
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
buttonPressed(1);
}
});
button2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
buttonPressed(2);
}
});
button3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
buttonPressed(3);
}
});
unpairB.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
unpair(selected);
finish();
}
});
// Set up textview
tv = (TextView) findViewById(R.id.textView);
tv.setText("connected to: " + selected.getName());
}
protected void buttonPressed(int i) {
connectedThread.write(i);
tv.setText(Integer.toString(i));
}
private void pair(BluetoothDevice device) {
connectThread = new ConnectThread(device);
connectThread.start();
}
private void unpair(BluetoothDevice device) {
try {
Method m = device.getClass().getMethod("removeBond", (Class[]) null);
m.invoke(device, (Object[]) null);
} catch (Exception e) {
Log.e("unpair()", e.getMessage());
}
}
private class ConnectThread extends Thread {
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
// Use a temporary object that is later assigned to mmSocket,
// because mmSocket is final
BluetoothSocket tmp = null;
mmDevice = device;
// Get a BluetoothSocket to connect with the given BluetoothDevice
try {
// MY_UUID is the app's UUID string, also used by the server code
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
System.out.println("Socket was created in ConnectThread");
} catch (IOException e) { }
mmSocket = tmp;
}
public void run() {
// Cancel discovery because it will slow down the connection
// bluetoothAdapter.cancelDiscovery();
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
mmSocket.connect();
} catch (IOException connectException) {
// Unable to connect; close the socket and get out
try {
mmSocket.close();
} catch (IOException closeException) { }
return;
}
// Do work to manage the connection (in a separate thread)
//manageConnectedSocket(mmSocket);
}
/** Will cancel an in-progress connection, and close the socket */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
private class ConnectedThread extends Thread {
private final BluetoothSocket bluetoothSocket;
private final InputStream inputStream;
private final OutputStream outputStream;
public ConnectedThread(BluetoothSocket socket) {
this.bluetoothSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
System.out.println("Connected to " + socket.getRemoteDevice().getName());
try {
tmpIn = bluetoothSocket.getInputStream();
tmpOut = bluetoothSocket.getOutputStream();
} catch (IOException e) {
}
inputStream = tmpIn;
outputStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[1024];
int bytes;
if (inputStream == null) System.out.println("Inputstream is null");
else System.out.println("Inputstream is safe");
if (outputStream == null) System.out.println("outstream is null");
else System.out.println("Outputstream is safe");
while (true) {
try {
System.out.println("Blocking?");
bytes = inputStream.read(buffer);
System.out.println("NO");
handler.obtainMessage(MESSAGE_READ, bytes, -1,
buffer).sendToTarget();
} catch (IOException e) {
break;
}
}
}
public void write(int i) {
try {
byte[] buffer = new byte[1024];
buffer[0] = (byte) i;
outputStream.write(buffer);
outputStream.flush();
handler.obtainMessage(MESSAGE_WRITE, -1, -1,
buffer).sendToTarget();
System.out.println("Write SUCCESS!!!!!!!!!!!!!!");
} catch (IOException e) {
System.out.println("write ERRORRRRRRRRRRRRRRRRR");
}
}
public void cancel() {
try {
bluetoothSocket.close();
} catch (IOException e) {
}
}
}
private final Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_WRITE:
System.out.println("Write was broadcasted");
byte[] writeBuf = (byte[]) msg.obj;
String writeMessage = new String(Integer.toString(writeBuf[0]));
///tv.setText(writeMessage);
break;
case MESSAGE_READ:
System.out.println("Read was broadcasted");
byte[] readBuf = (byte[]) msg.obj;
String readMessage = new String(Integer.toString(readBuf[0]));
tv.setText(readMessage);
break;
}
}
};
}
I am trying to save an array list into a xml file in the internal storage using Xmlserializer. The app scans for BLE and when a Stop button is pressed it should save some parameters from the list of BLE that it has detected. It runs perfect and when I pressed the stop button it stops the scan and displays in the mobile screen a toast message that the xml file has been created successfully. However, when I seach for the xml file, it doesn´t appear anywhere as if it hasn´t been created. I don´t know the reason of this problem. Here is the code I have implemented:
package com.example.newblescan;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import org.xmlpull.v1.XmlSerializer;
import com.example.newblescan.R;
import android.app.Activity;
import android.app.ListActivity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.text.format.DateFormat;
import android.util.Xml;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ListView;
import android.widget.Toast;
import com.example.newblescan.adapter.BleDevicesAdapter;
/**
* Activity for scanning and displaying available Bluetooth LE devices.
*/
public class DeviceScanActivity extends ListActivity {
private static final int REQUEST_ENABLE_BT = 1;
private static final long SCAN_PERIOD = 100;
private BleDevicesAdapter leDeviceListAdapter;
private BluetoothAdapter bluetoothAdapter;
private Scanner scanner;
private Save save;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActionBar().setTitle(R.string.title_devices);
// Use this check to determine whether BLE is supported on the device. Then you can
// selectively disable BLE-related features.
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
finish();
return;
}
// Initializes a Bluetooth adapter. For API level 18 and above, get a reference to
// BluetoothAdapter through BluetoothManager.
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
bluetoothAdapter = bluetoothManager.getAdapter();
// Checks if Bluetooth is supported on the device.
if (bluetoothAdapter == null) {
Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show();
finish();
return;
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.gatt_scan, menu);
if (scanner == null || !scanner.isScanning()) {
menu.findItem(R.id.menu_stop).setVisible(false);
menu.findItem(R.id.menu_scan).setVisible(true);
menu.findItem(R.id.menu_refresh).setActionView(null);
} else {
menu.findItem(R.id.menu_stop).setVisible(true);
menu.findItem(R.id.menu_scan).setVisible(false);
menu.findItem(R.id.menu_refresh).setActionView(
R.layout.actionbar_indeterminate_progress);
}
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_scan:
leDeviceListAdapter.clear();
if (scanner == null) {
scanner = new Scanner(bluetoothAdapter, mLeScanCallback);
scanner.startScanning();
invalidateOptionsMenu();
}
break;
case R.id.menu_stop:
if (scanner != null) {
save = new Save(leDeviceListAdapter);
scanner.stopScanning();
try {
save.savedata();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
scanner = null;
invalidateOptionsMenu();
}
break;
}
return true;
}
#Override
protected void onResume() {
super.onResume();
// Ensures Bluetooth is enabled on the device. If Bluetooth is not currently enabled,
// fire an intent to display a dialog asking the user to grant permission to enable it.
if (!bluetoothAdapter.isEnabled()) {
final Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
return;
}
init();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// User chose not to enable Bluetooth.
if (requestCode == REQUEST_ENABLE_BT) {
if (resultCode == Activity.RESULT_CANCELED) {
finish();
} else {
init();
}
}
super.onActivityResult(requestCode, resultCode, data);
}
#Override
protected void onPause() {
super.onPause();
if (scanner != null) {
scanner.stopScanning();
scanner = null;
}
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
final BluetoothDevice device = leDeviceListAdapter.getDevice(position);
if (device == null)
return;
//final Intent intent = new Intent(this, DeviceServicesActivity.class);
//intent.putExtra(DeviceServicesActivity.EXTRAS_DEVICE_NAME, device.getName());
//intent.putExtra(DeviceServicesActivity.EXTRAS_DEVICE_ADDRESS, device.getAddress());
//startActivity(intent);
}
private void init() {
if (leDeviceListAdapter == null) {
leDeviceListAdapter = new BleDevicesAdapter(getBaseContext());
setListAdapter(leDeviceListAdapter);
}
if (scanner == null) {
scanner = new Scanner(bluetoothAdapter, mLeScanCallback);
scanner.startScanning();
}
invalidateOptionsMenu();
}
// Device scan callback.
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(final BluetoothDevice device, final int rssi, byte[] scanRecord) {
runOnUiThread(new Runnable() {
#Override
public void run() {
leDeviceListAdapter.addDevice(device, rssi);
leDeviceListAdapter.notifyDataSetChanged();
}
});
}
};
private static class Scanner extends Thread {
private final BluetoothAdapter bluetoothAdapter;
private final BluetoothAdapter.LeScanCallback mLeScanCallback;
private volatile boolean isScanning = false;
Scanner(BluetoothAdapter adapter, BluetoothAdapter.LeScanCallback callback) {
bluetoothAdapter = adapter;
mLeScanCallback = callback;
}
public boolean isScanning() {
return isScanning;
}
public void startScanning() {
synchronized (this) {
isScanning = true;
start();
}
}
public void stopScanning() {
synchronized (this) {
isScanning = false;
bluetoothAdapter.stopLeScan(mLeScanCallback);
}
}
#Override
public void run() {
try {
while (true) {
synchronized (this) {
if (!isScanning)
break;
bluetoothAdapter.startLeScan(mLeScanCallback);
}
sleep(SCAN_PERIOD);
synchronized (this) {
bluetoothAdapter.stopLeScan(mLeScanCallback);
}
}
} catch (InterruptedException ignore) {
} finally {
bluetoothAdapter.stopLeScan(mLeScanCallback);
}
}
}
public class Save {
/**
*
*/
private BleDevicesAdapter leDeviceListAdapter;
Save(BleDevicesAdapter BLEList) {
leDeviceListAdapter = BLEList;
}
public void savedata() throws FileNotFoundException{
String filename = "Dragon.txt";
//String date = (DateFormat.format("dd-MM-yyyy hh:mm:ss", new java.util.Date()).toString());
FileOutputStream fos = null;
int size = leDeviceListAdapter.getCount();
//Bundle extras = getIntent().getExtras();
//long timestamp = extras.getLong("currentTime");
try {
fos= openFileOutput(filename, Context.MODE_PRIVATE);
XmlSerializer serializer = Xml.newSerializer();
serializer.setOutput(fos, "UTF-8");
serializer.startDocument(null, Boolean.valueOf(true));
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
serializer.startTag("", "root");
//serializer.startTag("", "timestamp");
//serializer.text(date);
//serializer.endTag("", "timestamp");
for(int j = 0 ; j < size ; j++)
{
BluetoothDevice devices = leDeviceListAdapter.getDevice(j);
//Integer signal = leDeviceListAdapter.getRSSI(j);
serializer.startTag("", "name");
serializer.text(devices.getName());
serializer.endTag("", "name");
serializer.startTag("", "address");
serializer.text(devices.getAddress());
serializer.endTag("", "address");
//serializer.startTag(null, "rssi");
//serializer.setProperty(null, signal);
//serializer.endTag(null, "rssi");
}
//ObjectOutputStream out = new ObjectOutputStream(fos);
//out.write((int) timestamp);
//out.writeObject(leDeviceListAdapter);
//out.close();
serializer.endDocument();
serializer.flush();
fos.close();
Toast.makeText(DeviceScanActivity.this, R.string.list_saved, Toast.LENGTH_SHORT).show();
} catch (FileNotFoundException e){
e.printStackTrace();
} catch (IOException e){
e.printStackTrace();
}
}
}
}
In the class Save, I implement the method savedata to save the list into a xml file.
Does anyone know what is the problem? Pleasee help!!!!
openFileOutput puts it in the /data/data/your_packagename/files directory. This directory can only be read by root and by your app- you will not be able to find the file in any other program without rooting your device. You will not be able to find it in a file explorer unless you have root access. If you want to be able to see the file, you need to write it somewhere world accessible, such as the sd card.
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.