I am building android app which have to listen all the time (constantly) a voice and catch a key word like eg help. I am using now MediaRecorder to get an amplitude, then if is loud (eg 20000), I call pocketsphinx speechrecognizer. The problem is that when speechrecognizer caught (or not) the key word I can't jump back to MediaRecorder, the app is crashed. Of course my app must work in the background (24 h/day) so my implementation is in Service, so my MediaRecorder is in separate thread.
I know that pocketsphinx can check also the amplitude (a scream), but how to make it? And is pocketsphinx (get amplitude) better solution to trigger the speech recognizer? Below my class, I would be very appreciate for any help.
#Override
public IBinder onBind(Intent intent) {
return null;
}
private final class ServiceHandler extends Handler{
public ServiceHandler(Looper looper){
super(looper);
}
#Override
public void handleMessage(Message msg){
outputFile = Environment.getExternalStorageDirectory().getAbsolutePath() + "/record.3gp";
getVoiceRecord();
}
}
#Override
public void onCreate() {
thread = new HandlerThread("ServiceStartArguments",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
// Get the HandlerThread's Looper and use it for our Handler
serviceLooper = thread.getLooper();
serviceHandler = new ServiceHandler(serviceLooper);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//TODO do something useful
//change to START_STICKY
Log.d("tag", "on start command");
Message msg = serviceHandler.obtainMessage();
msg.arg1 = startId;
serviceHandler.sendMessage(msg);
return Service.START_NOT_STICKY;
}
private void getVoiceRecord() {
startRecorder();
start = System.currentTimeMillis();
Log.d("tag", "Time started at " + start);
while (true){
if(recorder!=null){
amplitude = recorder.getMaxAmplitude();
if(amplitude>20000){
Toast.makeText(getApplicationContext(), "Scream detected",
Toast.LENGTH_LONG).show();
Log.d("tag", "Scream detected " + 20 * Math.log10(amplitude) + " amplitude: " + amplitude);
stopRecorder();
Log.d("tag", "Finish recording");
getSpeech();
}
finish = System.currentTimeMillis();
if(finish-start>50000){
//loop = false;
stopRecorder();
Log.d("tag", "Finish recording");
if(recorder==null){
recorder.reset();
startRecorder();
start = System.currentTimeMillis();
}
}
}
}//end of while loop
}
private void getSpeech() {
try {
Assets assets = new Assets(ScreamService.this);
File assetDir = assets.syncAssets();
setupRecognizer(assetDir);
} catch (IOException e) {
//return e;
}
reset();
}
private void stopRecorder() {
try{
recorder.stop();
recorder.reset();
recorder.release();
recorder = null;
Log.d("tag", "Stop recording");
}catch (IllegalStateException e) {
e.printStackTrace();
Log.d("tag", "Media Recorder did not stop " + e);
try {
Thread.sleep(2000);
recorder.stop();
recorder.release();
recorder = null;
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}catch (RuntimeException e) {
e.printStackTrace();
Log.d("tag", "Media Recorder did not stop " + e);
}
}
private void startRecorder() {
Log.d("tag", "Start recording... ");
try {
recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(outputFile);
recorder.prepare();
recorder.start();
} catch (IOException e) {
e.printStackTrace();
Log.d("tag", "Media Recorder did not start IOExeption " + e);
} catch (IllegalStateException e) {
e.printStackTrace();
Log.d("tag", "Media Recorder did not start Ilegal State Trace" + e);
}
}
#Override
public void onDestroy() {
super.onDestroy();
recognizer.cancel();
recognizer.shutdown();
Toast.makeText(this, "Scream Service & recognizer Stopped.", Toast.LENGTH_SHORT).show();
}
#Override
public void onPartialResult(Hypothesis hypothesis) {
}
/**
* This callback is called when we stop the recognizer.
*/
#Override
public void onResult(Hypothesis hypothesis) {
if (hypothesis != null) {
String text = hypothesis.getHypstr();
//makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();
Log.d("tag", "onResult " + text);
if(text.equals("help") || text.equals("help me")) {
recognizer.stop();
recognizer.cancel();
this.startService(new Intent(this, SendMessage.class));
getVoiceRecord();
}
}else {
Log.d("tag", "onResult is null");
}
}
#Override
public void onBeginningOfSpeech() {
//Log.d("tag", "onBeginningOfSpeech ");
}
#Override
public void onEndOfSpeech() {
counter++;
if(counter>5){
//recognizer.stop();
recognizer.cancel();
counter=0;
getVoiceRecord();
Log.d("tag", "Speech recognizer is killed");
}else {
//Log.d("tag", "onEndOfSpeech ");
reset();
}
}
private void reset() {
recognizer.stop();
recognizer.startListening("menu");
}
private void setupRecognizer(File assetsDir) throws IOException {
Log.d("tag", "default setup");
recognizer = defaultSetup()
.setAcousticModel(new File(assetsDir, "en-us-ptm"))
.setDictionary(new File(assetsDir, "cmudict-en-us.dict"))
// To disable logging of raw audio comment out this call (takes a lot of space on the device)
.setRawLogDir(assetsDir)
// Threshold to tune for keyphrase to balance between false alarms and misses
.setKeywordThreshold(1e-45f)
// Use context-independent phonetic search, context-dependent is too slow for mobile
.setBoolean("-allphone_ci", true)
.getRecognizer();
recognizer.addListener(this);
// Create grammar-based search for selection between demos
File menuGrammar = new File(assetsDir, "menu.gram");
recognizer.addGrammarSearch("menu", menuGrammar);
}
#Override
public void onError(Exception error) {
Log.d("tag", "error "+error.getMessage());
}
#Override
public void onTimeout() {
Log.d("tag", "onTimeout");
}
You can modify pocketsphinx sources to compute amplitude of recorded audio data before you pass it into recognizer. In SpeechRecognizer.java RecognizerThread class:
.........
while (!interrupted()
&& ((timeoutSamples == NO_TIMEOUT) || (remainingSamples > 0))) {
int nread = recorder.read(buffer, 0, buffer.length);
if (-1 == nread) {
throw new RuntimeException("error reading audio buffer");
} else if (nread > 0) {
// int max = 0;
// for (int i = 0; i < nread; i++) {
// max = Math.max(max, Math.abs(buffer[i]));
// }
// Log.e("!!!!!!!!", "Level is: " + max);
// You can decide to skip buffer here
decoder.processRaw(buffer, nread, false, false);
......
Related
What i try to do is to record a sound after to upload it into firebase
and to retrieve then into reciclerview were i can control the
play/stop and the progress. Like whatsApp audio messages
The class AudioPlayer its called in the Main activity by pressing a
button and return the value to upload the file in firebase.Its work
but the sound quality its very poor and its work just in browser or
directly in source folder or i can t play it in other formats like
THREE_GPP just when i play it directly in the source folder.
public class StartRecordMessage extends AppCompatActivity implements Runnable {
private static String fileName = null;
private MediaRecorder myAudioRecorder;
private MediaPlayer player = null;
private boolean permissionToRecordAccepted = false;
private String[] permissions = {Manifest.permission.RECORD_AUDIO};
private final String TAG = "StartRecordMessageClass";
private String audioName = null;
private String externalStoragePath,externalOutputPath,storagePath;
public StartRecordMessage(MediaRecorder myAudioRecorder) {
this.myAudioRecorder = myAudioRecorder;
}
#Override
public void run() {
startRecording();
}
public String startRecording (){
myAudioRecorder = new MediaRecorder();
myAudioRecorder.reset();
myAudioRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
myAudioRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
myAudioRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
{
externalStoragePath = Environment.getExternalStorageDirectory().getAbsolutePath();
externalOutputPath = externalStoragePath + File.separator + "/Android/data/test.mp3";
myAudioRecorder.setOutputFile(externalOutputPath);
}
else
{
storagePath = Environment.getDataDirectory().getAbsolutePath();
myAudioRecorder.setOutputFile(storagePath + "/Android/data/test.mp3");
}
try {
Log.i(TAG, "--------------recording started confirmed" + externalOutputPath + storagePath );
myAudioRecorder.prepare();
myAudioRecorder.start();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (externalOutputPath.isEmpty()){
return storagePath;
}else {
return externalOutputPath;
}
}
Follow method is in the main activity
#Override
public void onRecordingCompleted() {
Log.i(TAG, "---------completed");
startThread = new Thread(new StartRecordMessage(myAudioRecorder));
startThread.start();
startRecordMessage = new StartRecordMessage(myAudioRecorder);
audioMessage = startRecordMessage.startRecording();
Log.i(TAG, "recordingCompleted--------------" + audioMessage);
UploadSound(audioMessage);
}
messageListAdapter.notifyDataSetChanged();
}
AudioPlayerClass
public class AudioPlayer {
public static void play(Context ctx, String path) {
try {
final AudioManager audioManager = (AudioManager) ctx.getSystemService(Context.AUDIO_SERVICE);
final int currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
final MediaPlayer mediaPlayer = MediaPlayer.create(ctx, Uri.parse(path));
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
if (!audioManager.isWiredHeadsetOn()) {
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, currentVolume, AudioManager.FLAG_VIBRATE);
}
mp.release();
}
});
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
if (!audioManager.isWiredHeadsetOn()) {
int volume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC) / 2;
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume, AudioManager.FLAG_VIBRATE);
}
mp.start();
}
});
} catch(
Throwable e)
{
Log.i("AudioUtil", "Unable to play: " + path, e);
}
}
}
AdapterClass
holder.playStop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
clickCount++;
if (clickCount==1) {
isPlayng=true;
holder.playStop.setBackgroundResource(R.drawable.ic_pause);
Log.i(TAG,"audio url---------------" + audio);
audioPlayer = new AudioPlayer();
audioPlayer.play(context,audio);
Log.i(TAG, "Media player ------------"+ clickCount + " is play: " +isPlayng);
}
if (clickCount>1){
isPlayng=false;
clickCount=0;
holder.playStop.setBackgroundResource(R.drawable.ic_play);
Log.i(TAG, "Media player ------------" + clickCount + " is play: " + isPlayng);
}
}
});
The follow error is triggered when i want to play the sound. The class
Audio player class is called in Adapter class but the problem is the
url.
https://firebasestorage.googleapis.com/v0/b/chat-b18d3.appspot.com/o/Audio%.....
2020-11-12 22:59:44.739 2621-2621 I/AudioUtil: Unable to play: https://firebasestorage.googleapis.com/v0/b/chat-b18d3.appspot.com/o/Audio%.....
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object
android.content.Context.getSystemService(java.lang.String)' on a null
object reference
at com.example....ChatRecord.AudioPlayer.play(AudioPlayer.java:13)
at com.example.chatMapOriginal.Profile.Chat.MyGroups.GroupChatAdapter$1.onClick(GroupChatAdapter.java:137)
at android.view.View.performClick(View.java:7192)
at android.view.View.performClickInternal(View.java:7166)
at android.view.View.access$3500(View.java:824)
at android.view.View$PerformClick.run(View.java:27592)
at android.os.Handler.handleCallback(Handler.java:888)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:213)
at android.app.ActivityThread.main(ActivityThread.java:8178)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101)
try add values in your media file.
exmaple.
// Setup values for the media file
ContentValues values = new ContentValues(4);
long current = System.currentTimeMillis();
values.put(MediaStore.Audio.Media.TITLE, "audio file");
values.put(MediaStore.Audio.Media.DATE_ADDED, (int) (current / 1000));
values.put(MediaStore.Audio.Media.MIME_TYPE, "audio/3gpp");
values.put(MediaStore.Audio.Media.DATA, audiofile.getAbsolutePath());
ContentResolver contentResolver = getContentResolver();
// Construct uris
Uri base = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
Uri newUri = contentResolver.insert(base, values);
// Trigger broadcast to add
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, newUri));
Toast.makeText(this, "Added File " + newUri, Toast.LENGTH_LONG).show();
this code from here
I'm trying to write a code I can write all the results values from accelerometer sensor into a .txt file. I can't write all the data in somehow. I think there is a problem in my loop. It is just reading about 10 to 15 samples.
How can I write all the values of the sensor into that file until I toggle off the button to stop? here is the code I wrote.
Thanks in advance!
public class MainActivity extends Activity implements SensorEventListener {
public SensorManager sm;
Sensor accelermeter;
private static final String DEBUG = "LogAccelermeter";
ToggleButton OnStore;
Button OffStore;
Button btnOn, btnOff;
TextView txtArduino, txtString, txtStringLength, sensorView0, sensorView1, sensorView2, sensorView3;
Handler bluetoothIn;
final int handlerState = 0; //used to identify handler message
private BluetoothAdapter btAdapter = null;
private BluetoothSocket btSocket = null;
private StringBuilder recDataString = new StringBuilder();
private ConnectedThread mConnectedThread;
// SPP UUID service - this should work for most devices
private static final UUID BTMODULEUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
TextView sensorText;
// String for MAC address
private static String address;
private GestureDetectorCompat mDetector;
FileOutputStream fileOutputStream;
double TotalAccelerate;
ArrayList<Double> list;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list = new ArrayList<Double>();
//Link the buttons and textViews to respective views
btnOn = (Button) findViewById(R.id.buttonOn);
btnOff = (Button) findViewById(R.id.buttonOff);
txtString = (TextView) findViewById(R.id.txtString);
txtStringLength = (TextView) findViewById(R.id.testView1);
sensorView0 = (TextView) findViewById(R.id.sensorView0);
sensorView1 = (TextView) findViewById(R.id.sensorView1);
sensorView2 = (TextView) findViewById(R.id.sensorView2);
sensorView3 = (TextView) findViewById(R.id.sensorView3);
//for Accelermeter
sm = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensorText = (TextView) findViewById(R.id.sensor);
accelermeter = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sm.registerListener(this, accelermeter, SensorManager.SENSOR_DELAY_NORMAL);
mDetector = new GestureDetectorCompat(this, new MyGestureListener());
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
File Root = Environment.getExternalStorageDirectory();
File dir = new File(Root.getAbsolutePath() + "/MyApp");
if (!dir.exists()) {
dir.mkdir();
}
File file = new File(dir, "MyMessage.txt");
try {
fileOutputStream = new FileOutputStream(file, true);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
} else {
Toast.makeText(getApplicationContext(), "SDcard not found", Toast.LENGTH_LONG).show();
}
OnStore = (ToggleButton) findViewById(R.id.onStore);
OnStore.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
if (OnStore.isChecked()){
try {
for(double TotalAccelerate : list){
// System.out.println("final"+ TotalAccelerate);
String space = "\n";
byte[] convert = space.getBytes();
fileOutputStream.write(convert);
String finalData;
finalData = String.valueOf(TotalAccelerate);
fileOutputStream.write(finalData.getBytes());
Log.i(DEBUG, "ans: " + finalData);
}
// fileOutputStream.close();
Toast.makeText(getApplicationContext(), "Message saving", Toast.LENGTH_LONG).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}if (!OnStore.isChecked()){
try {
fileOutputStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
try {
fileOutputStream.close();
list.clear();
Collections.synchronizedList(list);
} catch (IOException e) {
e.printStackTrace();
}
Toast.makeText(getApplicationContext(),"Message Stopped.",Toast.LENGTH_LONG).show();
}
}
});
bluetoothIn = new Handler() {
public void handleMessage(android.os.Message msg) {
if (msg.what == handlerState) { //if message is what we want
String readMessage = (String) msg.obj; // msg.arg1 = bytes from connect thread
recDataString.append(readMessage); //keep appending to string until ~
int endOfLineIndex = recDataString.indexOf("~"); // determine the end-of-line
if (endOfLineIndex > 0) { // make sure there data before ~
String dataInPrint = recDataString.substring(0, endOfLineIndex); // extract string
txtString.setText("Data Received = " + dataInPrint);
int dataLength = dataInPrint.length(); //get length of data received
txtStringLength.setText("String Length = " + String.valueOf(dataLength));
if (recDataString.charAt(0) == '#') //if it starts with # we know it is what we are looking for
{
String sensor0 = recDataString.substring(1, 5); //get sensor value from string between indices 1-5
String sensor1 = recDataString.substring(6, 10); //same again...
String sensor2 = recDataString.substring(11, 15);
String sensor3 = recDataString.substring(16, 20);
sensorView0.setText(" Sensor 0 Voltage = " + sensor0 + "V"); //update the textviews with sensor values
sensorView1.setText(" Sensor 1 Voltage = " + sensor1 + "V");
sensorView2.setText(" Sensor 2 Voltage = " + sensor2 + "V");
sensorView3.setText(" Sensor 3 Voltage = " + sensor3 + "V");
}
recDataString.delete(0, recDataString.length()); //clear all string data
// strIncom =" ";
dataInPrint = " ";
}
}
}
};
btAdapter = BluetoothAdapter.getDefaultAdapter(); // get Bluetooth adapter
checkBTState();
// Set up onClick listeners for buttons to send 1 or 0 to turn on/off LED
btnOff.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mConnectedThread.write("0"); // Send "0" via Bluetooth
Toast.makeText(getBaseContext(), "Turn off LED", Toast.LENGTH_SHORT).show();
}
});
btnOn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mConnectedThread.write("1"); // Send "1" via Bluetooth
Toast.makeText(getBaseContext(), "Turn on LED", Toast.LENGTH_SHORT).show();
}
});
}//end OnCreate Method
#Override
public final void onAccuracyChanged(Sensor sensor, int accuracy) {
// Do something here if sensor accuracy changes.
}
#Override
public final void onSensorChanged(SensorEvent event) {
// The light sensor returns a single value.
// Many sensors return 3 values, one for each axis.
double xx = event.values[0];
double yy = event.values[1];
double zz = event.values[2];
TotalAccelerate = Math.round(Math.sqrt(Math.pow(xx, 2)
+ Math.pow(yy, 2)
+ Math.pow(zz, 2)));
Log.i(DEBUG, "Accelerometer = " + TotalAccelerate);
list.add(TotalAccelerate);
findPeaks(list);
sensorText.setText("Total: " + TotalAccelerate);
Log.i(DEBUG, "list values " + list);
}
//Find peak values.
public static ArrayList<Double> findPeaks(List<Double> points) {
ArrayList<Double> peaks = new ArrayList<Double>();
if (points == null || points.size() < 1)
return peaks;
Double x1_n_ref = 0.0;
int alpha = 0; //0=down, 1=up.
int size = points.size();// -1)/100;
for (int i = 0; i < size; i += 5) {
Double IndexValues = points.get(i);
if (IndexValues > 9) {
Double delta = (x1_n_ref - IndexValues);
if (delta < 0) {
x1_n_ref = IndexValues;
alpha = 1;
} else if (alpha == 1 && delta > 0) {
peaks.add(x1_n_ref);
alpha = 0;
}
} else if (alpha == 0) {
x1_n_ref = IndexValues;
}
}
return peaks;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
this.mDetector.onTouchEvent(event);
return super.onTouchEvent(event);
}
class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
private static final String DEBUG_TAG = "Gestures";
#Override
public boolean onDown(MotionEvent event) {
Log.d(DEBUG_TAG, "onDown: " + event.toString());
Toast.makeText(getApplication(), "OnDown Touch Occur", Toast.LENGTH_LONG).show();
if (event.getX() > 0) {
mConnectedThread.write("1");
}
return true;
}
#Override
public void onLongPress(MotionEvent event) {
Log.d(DEBUG_TAG, "onLongPress: " + event.toString());
mConnectedThread.write("0");
}
private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOException {
return device.createRfcommSocketToServiceRecord(BTMODULEUUID);
//creates secure outgoing connecetion with BT device using UUID
}
#Override
public void onResume() {
super.onResume();
//Get MAC address from DeviceListActivity via intent
Intent intent = getIntent();
//Get the MAC address from the DeviceListActivty via EXTRA
address = intent.getStringExtra(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
//create device and set the MAC address
BluetoothDevice device = btAdapter.getRemoteDevice(address);
try {
btSocket = createBluetoothSocket(device);
} catch (IOException e) {
Toast.makeText(getBaseContext(), "Socket creation failed", Toast.LENGTH_LONG).show();
}
// Establish the Bluetooth socket connection.
try {
btSocket.connect();
} catch (IOException e) {
try {
btSocket.close();
} catch (IOException e2) {
//insert code to deal with this
}
}
mConnectedThread = new ConnectedThread(btSocket);
mConnectedThread.start();
//I send a character when resuming.beginning transmission to check device is connected
//If it is not an exception will be thrown in the write method and finish() will be called
mConnectedThread.write("x");
}
#Override
public void onPause() {
super.onPause();
try {
//Don't leave Bluetooth sockets open when leaving activity
btSocket.close();
} catch (IOException e2) {
//insert code to deal with this
}
}
//Checks that the Android device Bluetooth is available and prompts to be turned on if off
private void checkBTState() {
if (btAdapter == null) {
Toast.makeText(getBaseContext(), "Device does not support bluetooth", Toast.LENGTH_LONG).show();
} else {
if (btAdapter.isEnabled()) {
} else {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, 1);
}
}
}
//create new class for connect thread
private class ConnectedThread extends Thread {
private final InputStream mmInStream;
private final OutputStream mmOutStream;
//creation of the connect thread
public ConnectedThread(BluetoothSocket socket) {
InputStream tmpIn = null;
OutputStream tmpOut = null;
try {
//Create I/O streams for connection
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[256];
int bytes;
// Keep looping to listen for received messages
while (true) {
try {
bytes = mmInStream.read(buffer); //read bytes from input buffer
String readMessage = new String(buffer, 0, bytes);
// Send the obtained bytes to the UI Activity via handler
bluetoothIn.obtainMessage(handlerState, bytes, -1, readMessage).sendToTarget();
} catch (IOException e) {
break;
}
}
}
//write method
public void write(String input) {
byte[] msgBuffer = input.getBytes(); //converts entered String into bytes
try {
mmOutStream.write(msgBuffer); //write bytes over BT connection via outstream
} catch (IOException e) {
//if you cannot write, close the application
Toast.makeText(getBaseContext(), "Connection Failure", Toast.LENGTH_LONG).show();
finish();
}
}
}
}
Could you try this for the toggle button onClick callback? It should write all the data when it's unchecked.
OnStore.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
if (OnStore.isChecked()){
// should do nothing
} else if (!OnStore.isChecked()){
try {
for(double TotalAccelerate : list){
//System.out.println("final"+ TotalAccelerate);
String space = "\n";
byte[] convert = space.getBytes();
fileOutputStream.write(convert);
String finalData;
finalData = String.valueOf(TotalAccelerate);
fileOutputStream.write(finalData.getBytes());
Log.i(DEBUG, "ans: " + finalData);
}
fileOutputStream.flush();
fileOutputStream.close();
Toast.makeText(getApplicationContext(), "Message saving", Toast.LENGTH_LONG).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Toast.makeText(getApplicationContext(),"Message Stopped.",Toast.LENGTH_LONG).show();
}
}
});
To regulate the code to start/stop listen to the sensor event, add the following variable somewhere in this class:
private boolean isListening = false;
And make the following modifications to your existing code:
OnStore.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
if (OnStore.isChecked()){
//
// set listening flag to true
//
isListening = true;
} else if (!OnStore.isChecked()){
//
// set listening flag to false
//
isListening = false;
try {
for(double TotalAccelerate : list){
//System.out.println("final"+ TotalAccelerate);
String space = "\n";
byte[] convert = space.getBytes();
fileOutputStream.write(convert);
String finalData;
finalData = String.valueOf(TotalAccelerate);
fileOutputStream.write(finalData.getBytes());
Log.i(DEBUG, "ans: " + finalData);
}
fileOutputStream.flush();
fileOutputStream.close();
Toast.makeText(getApplicationContext(), "Message saving", Toast.LENGTH_LONG).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Toast.makeText(getApplicationContext(),"Message Stopped.",Toast.LENGTH_LONG).show();
}
}
});
#Override
public final void onSensorChanged(SensorEvent event) {
// The light sensor returns a single value.
// Many sensors return 3 values, one for each axis.
//
// regulate
//
if (isListening) {
double xx = event.values[0];
double yy = event.values[1];
double zz = event.values[2];
TotalAccelerate = Math.round(Math.sqrt(Math.pow(xx, 2)
+ Math.pow(yy, 2)
+ Math.pow(zz, 2)));
Log.i(DEBUG, "Accelerometer = " + TotalAccelerate);
list.add(TotalAccelerate);
findPeaks(list);
sensorText.setText("Total: " + TotalAccelerate);
Log.i(DEBUG, "list values " + list);
}
}
I'm handling a Bluetooth connection on the MainActivity class of my app. I'd like to send the data when a touch event occurs in my custom view.
public boolean onTouch(View v, MotionEvent event) {
int action=event.getActionMasked();
...
if(action==1){
MainActivity.sendData("P,S," + stringvelocidad + ","+stringrotacion+"&");
}
But there's no way to access a non-static method from a static one. Which ways I have to do this on a proper way?
This is sendData() method:
public void sendData(String message) {
try {
outStream=btSocket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
byte[] msgBuffer = message.getBytes();
Log.d(TAG, "...Sending data: " + message + "...");
try {
outStream.write(msgBuffer);
} catch (IOException e) {
}
try {
outStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
I post whole code
public class EjemploView extends View implements View.OnTouchListener {
private Drawable drawableFader, drawableSlider, drawableLogo;
private Grafico fader1, fader2, slider1, slider2,logo;
Paint pincel=new Paint();
private String stringvelocidad="0",stringrotacion="0";
private int slider1cero,slider2cero;
int oldvelocidad=0;
int oldrotacion=0;
// Cada cuanto queremos procesar cambios (ms)
private static long PERIODO_PROCESO = 1000000;
// Cuando se realizó el último proceso
private long ultimoProceso = 0;
public EjemploView(Context context, AttributeSet attrs) {
super(context,attrs);
setOnTouchListener(this);
Resources res = context.getResources();
drawableFader = res.getDrawable(R.drawable.fader);
drawableSlider=res.getDrawable(R.drawable.slider);
drawableLogo=res.getDrawable(R.drawable.logo);
fader1 = new Grafico(this, drawableFader);
fader2 = new Grafico(this, drawableFader);
slider1 = new Grafico(this, drawableSlider);
slider2 = new Grafico(this, drawableSlider);
logo=new Grafico(this,drawableLogo);
fader1.setAlto(350);
fader1.setAncho(64);
fader2.setAlto(350);
fader2.setAncho(64);
fader2.setAngulo(90);
slider1.setAlto(90);
slider1.setAncho(55);
slider2.setAlto(90);
slider2.setAncho(55);
slider2.setAngulo(90);
logo.setAncho(380);
logo.setAlto(120);
}
#Override
protected void onSizeChanged(int ancho, int alto, int ancho_anter, int alto_anter) {
super.onSizeChanged(ancho, alto, ancho_anter, alto_anter);
// Una vez que conocemos nuestro ancho y alto.
Hilo myThread = new Hilo();
myThread.start();
slider1cero=alto / 4 - 50;
slider2cero=ancho - 277;
fader1.setCenX(ancho / 4 - 31);
fader1.setCenY(alto / 4 - 50);
slider1.setCenX(ancho / 4 - 28);
slider1.setCenY(alto / 4 - 50);
fader2.setCenX(ancho - 271);
fader2.setCenY(alto / 4 - 50);
slider2.setCenX(ancho - 277);
slider2.setCenY(alto / 4 - 50);
logo.setCenX(ancho - 277);
logo.setCenY(100);
}
#Override
synchronized protected void onDraw(Canvas canvas) {
pincel.setColor(Color.BLACK);
pincel.setTextSize(30);
canvas.drawText("Velocidad:", 300, 390, pincel);
canvas.drawText("Rotación:", 300, 430, pincel);
canvas.drawText(stringvelocidad, 450, 390, pincel);
canvas.drawText(stringrotacion, 450, 430, pincel);
fader1.dibujaGrafico(canvas);
fader2.dibujaGrafico(canvas);
slider1.dibujaGrafico(canvas);
slider2.dibujaGrafico(canvas);
logo.dibujaGrafico(canvas);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
int action=event.getActionMasked();
final float x=event.getX();
final float y=event.getY();
if(x>slider1.getCenX()-30 &&x<slider1.getCenX()+30 && y<fader1.getCenY()+fader1.getAlto()/2&&
y>fader1.getCenY()-fader1.getAlto()/2) {
slider1.setCenY((int) y);
}
if(y>fader2.getCenY()-30 &&y<fader2.getCenY()+31&& x<fader2.getCenX()+fader2.getAlto() / 2 &&
x > fader2.getCenX()-fader2.getAlto()/2) {
slider2.setCenX((int) x);
}
if(action==1){
MainActivity.sendData("P,S," + stringvelocidad + "," +stringrotacion+"&");
}
return true;
}
public class Hilo extends Thread {
public void run(){
while(true){
setspeed();
}
}
}
public void setspeed(){
long ahora = System.currentTimeMillis();
int velocidad=-1*(slider1.getCenY()-slider1cero);
int rotacion=slider2.getCenX()-slider2cero;
if (velocidad!=oldvelocidad||rotacion!=oldrotacion) {
stringvelocidad = String.valueOf((int)(velocidad*0.3));
stringrotacion = String.valueOf((int)(rotacion*0.3));
}
ultimoProceso = ahora;
oldvelocidad=velocidad;
oldrotacion=rotacion;
}
and code for Activity
public class MainActivity extends Activity {
private static final String TAG = "mensajes";
//-------BLUETOOTH VARIABLES--------//
private static final int REQUEST_ENABLE_BT = 1;
private BluetoothAdapter btAdapter = null;
private BluetoothSocket btSocket = null;
private OutputStream outStream = null;
// Well known SPP UUID
private static final UUID MY_UUID =
UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
// Insert your bluetooth devices MAC address
private static String address = "00:12:11:21:21:94";
//--------------------------------------//
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
setContentView(R.layout.activity_main);
btAdapter = BluetoothAdapter.getDefaultAdapter();
checkBTState();
}
#Override
protected void onDestroy() {
super.onDestroy();
}
#Override
public void onResume() {
super.onResume();
// Set up a pointer to the remote node using it's address.
BluetoothDevice device = btAdapter.getRemoteDevice(address);
// Two things are needed to make a connection:
// A MAC address, which we got above.
// A Service ID or UUID. In this case we are using the
// UUID for SPP.
try {
btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
errorExit("Fatal Error", "In onResume() and socket create failed: " + e.getMessage() + ".");
}
// Discovery is resource intensive. Make sure it isn't going on
// when you attempt to connect and pass your message.
btAdapter.cancelDiscovery();
// Establish the connection. This will block until it connects.
Log.d(TAG, "...Connecting to Remote...");
try {
btSocket.connect();
Log.d(TAG, "...Connection established and data link opened...");
} catch (IOException e) {
try {
btSocket.close();
} catch (IOException e2) {
errorExit("Fatal Error", "In onResume() and unable to close socket during connection failure" + e2.getMessage() + ".");
}
}
try {
outStream=btSocket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
//sendData("P");
}
public void onPause() {
super.onPause();
Log.d(TAG, "...In onPause()...");
if (outStream != null) {
try {
outStream.flush();
} catch (IOException e) {
errorExit("Fatal Error", "In onPause() and failed to flush output stream: " + e.getMessage() + ".");
}
}
try {
btSocket.close();
} catch (IOException e2) {
errorExit("Fatal Error", "In onPause() and failed to close socket." + e2.getMessage() + ".");
}
}
private void checkBTState() {
// Check for Bluetooth support and then check to make sure it is turned on
// Emulator doesn't support Bluetooth and will return null
if(btAdapter==null) {
errorExit("Fatal Error", "Bluetooth Not supported. Aborting.");
} else {
if (btAdapter.isEnabled()) {
Log.d(TAG, "...Bluetooth is enabled...");
} else {
//Prompt user to turn on Bluetooth
Intent enableBtIntent = new Intent(btAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
}
}
#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);
}
private void errorExit(String title, String message){
Toast msg = Toast.makeText(getBaseContext(),
title + " - " + message, Toast.LENGTH_SHORT);
msg.show();
finish();
}
public void sendData(String message) {
try {
outStream=btSocket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
byte[] msgBuffer = message.getBytes();
Log.d(TAG, "...Sending data: " + message + "...");
try {
outStream.write(msgBuffer);
} catch (IOException e) {
/*String msg = "In onResume() and an exception occurred during write: " + e.getMessage();
if (address.equals("00:00:00:00:00:00"))
msg = msg + ".\n\nUpdate your server address from 00:00:00:00:00:00 to the correct address on line 37 in the java code";
msg = msg + ".\n\nCheck that the SPP UUID: " + MY_UUID.toString() + " exists on server.\n\n";
errorExit("Fatal Error", msg);*/
}
try {
outStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
The solution has been creating a class handling all the Bluetooth connection and instatiating a public static object of this class in my Activity. That alows me to access its methods from the custom view.
So I'm trying to take multiple pictures at regular time intervals, however I get a "takePicture Failed" Exception after the first picture is previewed on the surfaceView.
Here's my takePictures() method which is called when a button is pressed:
public void takePictures() {
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
camera = Camera.open();
if (camera != null) {
try {
camera.setPreviewDisplay(surfaceView.getHolder());
camera.startPreview();
camera.takePicture(null, null, new CustomPictureCallbcak(this, cacheDir, imageView, 3, 5000));
}
catch (Exception e) {
e.printStackTrace();
}
}
}
else {
Toast.makeText(this, "No camera found.", Toast.LENGTH_SHORT).show();
}
}
And here's the onPictureTaken() method of CustomPictureCallback :
#Override
public void onPictureTaken(byte[] data, Camera camera) {
//get date info for file name
SimpleDateFormat sdf = new SimpleDateFormat("ddmmyyyyhhmmss");
String date = sdf.format(new Date());
String fileDir = createImageFileName(date);
//write the image to cache
writeImageToCache(fileDir, data);
//display file name in a toast notification
Toast.makeText(c, fileDir, Toast.LENGTH_SHORT).show();
//show picture on imageview
imageView.setImageBitmap(BitmapFactory.decodeByteArray(data, 0, data.length));
//retake images
this.camera = camera;
while (numOfImagesAlreadyTaken <= numOfImages) {
Thread thread = new Thread() {
#Override
public void run() {
// TODO Auto-generated method stub
super.run();
try {
numOfImagesAlreadyTaken++;
CustomPictureCallbcak.this.camera.stopPreview();
sleep(delay);
CustomPictureCallbcak.this.camera.takePicture(null, null, CustomPictureCallbcak.this);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
}
Toast.makeText(c, "Total images taken: " + numOfImagesAlreadyTaken, Toast.LENGTH_SHORT).show();
//release camera
camera.release();
camera = null;
}
As Aleksander Lidtke suggested, I created a single thread inside my takePictures() method and put a while loop inside it:
public void takePictures(final int numOfPictures, final int delay) {
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
Thread thread = new Thread() {
#Override
public void run() {
// TODO Auto-generated method stub
super.run();
while (numOfPicturesAlreadyTaken <= numOfPictures) {
try {
camera = Camera.open();
camera.setPreviewDisplay(surfaceView.getHolder());
camera.startPreview();
camera.takePicture(null, null, new CustomPictureCallbcak(MainActivity.this, cacheDir, imageView));
numOfPicturesAlreadyTaken++;
sleep(delay);
}
catch (Exception e) {
e.printStackTrace();
Log.d("TEST", e.getMessage());
}
}
}
};
thread.start();
}
else {
Toast.makeText(this, "No camera found.", Toast.LENGTH_SHORT).show();
}
}
Im currently developing a Music Player and due to the fact that each time the orientation changes on the Phone and the Activity is re-created, I wanted the music to be played by a service. This way, the user is able to leave the activity without the music stopping..
Now.. I have this weird issue I been unable to solve... Each time I created the Activity and Inflate the GUI, the service is started. But the Service always gets Bounded after the Activity has send the data... So the music never starts... I know this happens because if I add a Button to resend the data, the Music starts playing... Here is my code for the activity:
public class Player extends Activity{
private Cursor audioCursor;
public static int position=0;
private int count;
private boolean pause = false,
play= false,
stop= false,
next= false,
back= false,
playerActive= true,
dataChanged= false,
finished= false,
playing= true;
private String action;
Messenger mService = null;
boolean mIsBound;
final Messenger mMessenger = new Messenger(new IncomingHandler());
private ServiceConnection mConnection=null;
static final int MSG_SET_BOOLEAN_VALUE = 5;
static final int MSG_SET_STRING_VALUE = 4;
static final int MSG_SET_INT_VALUE = 3;
#Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.player);
Bundle extras = getIntent().getExtras();
action=extras.getString("action");
if(!(Background.isRunning()))
startService(new Intent(Player.this, Background.class));
doBindService();
if(action.equals("play")){
position=extras.getInt("position");
String[] proj = {
MediaStore.Audio.Media.ARTIST,
MediaStore.Audio.Media.TITLE,
MediaStore.Audio.Media.ALBUM,
MediaStore.Audio.Media.DURATION,
MediaStore.Audio.Media.IS_MUSIC,
MediaStore.Audio.Media.ALBUM_ID};
audioCursor = getContentResolver().query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, proj,
MediaStore.Audio.Media.IS_MUSIC, null,
MediaStore.Audio.Media.TITLE + " ASC");
startManagingCursor(audioCursor);
count = audioCursor.getCount();
inflatePlayer();
/////////////////////THIS IS THE CODE THAT ACTS BEFORE THE SERVICE CONNECTION
sendBoolToService(playerActive, "playerActive");
sendIntToService(position);
sendStringToService(action);
}
}
//THIS CODE MUST BE FASTER, BUT THE CONNECTION TAKES TOO LONG
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
mService = new Messenger(service);
Toast.makeText(getApplicationContext(), "ATTACHED!", Toast.LENGTH_LONG).show();
try {
Message msg = Message.obtain(null, Background.MSG_REGISTER_CLIENT);
msg.replyTo = mMessenger;
mService.send(msg);
} catch (RemoteException e) {
Toast.makeText(getApplicationContext(), "Connection failed!", Toast.LENGTH_LONG).show();
}
}
public void onServiceDisconnected(ComponentName className) {
mService = null;
Toast.makeText(getApplicationContext(), "UNATTACHED!", Toast.LENGTH_LONG).show();
}
};
private void inflatePlayer(){
//LOTS OF CODE FOR THE GUI, NOTHING TO DO WITH THE SERVICE... SO I OMITTED IT
}
#Override
protected void onStop(){
playerActive=false;
try {
doUnbindService();
} catch (Throwable t) {
}
if(!playing)
stopService(new Intent(Player.this, Background.class));
super.onStop();
}
#Override
protected void onDestroy(){
playerActive=false;
audioCursor.close();
try {
doUnbindService();
} catch (Throwable t) {
}
if(!playing)
stopService(new Intent(Player.this, Background.class));
super.onDestroy();
}
class IncomingHandler extends Handler {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SET_INT_VALUE:
String str = Integer.toString(msg.getData().getInt("int1"));
Toast.makeText(getApplicationContext(), "Int Message: " + str, Toast.LENGTH_LONG).show();
break;
case MSG_SET_STRING_VALUE:
String str1 = msg.getData().getString("str1");
break;
case MSG_SET_BOOLEAN_VALUE:
dataChanged=msg.getData().getBoolean("dataChanged");
finished=msg.getData().getBoolean("finished");
playing=msg.getData().getBoolean("playing");
if(!playing){
if(finished){
finished=false;
finish();
}
}
default:
super.handleMessage(msg);
}
}
}
private void sendIntToService(int intvaluetosend) {
if (mService != null) {
try {
Bundle b = new Bundle();
b.putInt("int1", intvaluetosend);
Message msg = Message.obtain(null, MSG_SET_INT_VALUE);
msg.setData(b);
mService.send(msg);
} catch (RemoteException e) {
}
}
}
private void sendStringToService(String stringtosend) {
if (mService != null) {
try {
Bundle b = new Bundle();
b.putString("str1", stringtosend);
Message msg = Message.obtain(null, MSG_SET_STRING_VALUE);
msg.setData(b);
mService.send(msg);
} catch (RemoteException e) {
}
}
}
private void sendBoolToService(boolean booltosend, String name) {
if (mService != null) {
try {
Bundle b = new Bundle();
b.putBoolean(name, booltosend);
Message msg = Message.obtain(null, MSG_SET_BOOLEAN_VALUE);
msg.setData(b);
mService.send(msg);
} catch (RemoteException e) {
}
}
}
void doBindService() {
bindService(new Intent(this, Background.class), mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
Toast.makeText(getApplicationContext(), "BOUND!", Toast.LENGTH_LONG).show();
}
void doUnbindService() {
if (mIsBound) {
if (mService != null) {
try {
Message msg = Message.obtain(null, Background.MSG_UNREGISTER_CLIENT);
msg.replyTo = mMessenger;
mService.send(msg);
} catch (RemoteException e) {
}
}
unbindService(mConnection);
mIsBound = false;
Toast.makeText(getApplicationContext(), "UNBOUND!", Toast.LENGTH_LONG).show();
}
}
}
The Service:
public class Background extends Service {
private NotificationManager nm;
private Cursor audioCursor;
MediaPlayer mp = new MediaPlayer();
private int count;
private boolean pause = false,
play= false,
stop= false,
next= false,
back= false,
playerActive= true,
dataChanged= false,
finished= false,
playing= false;
private int position;
private String action;
ArrayList<Messenger> mClients = new ArrayList<Messenger>();
static final int MSG_REGISTER_CLIENT = 1;
static final int MSG_UNREGISTER_CLIENT = 2;
static final int MSG_SET_INT_VALUE = 3;
static final int MSG_SET_STRING_VALUE = 4;
static final int MSG_SET_BOOLEAN_VALUE = 5;
final Messenger mMessenger = new Messenger(new IncomingHandler());
private static boolean isRunning = false;
private static final String TAG = "Background";
#Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
class IncomingHandler extends Handler {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_REGISTER_CLIENT:
mClients.add(msg.replyTo);
break;
case MSG_UNREGISTER_CLIENT:
mClients.remove(msg.replyTo);
break;
case MSG_SET_INT_VALUE:
position=msg.getData().getInt("int1");
break;
case MSG_SET_STRING_VALUE:
action=msg.getData().getString("str1");
if(action.equals("play")){
String[] proj = { MediaStore.Audio.Media.DATA,
MediaStore.Audio.Media.DURATION,
MediaStore.Audio.Media.IS_MUSIC,
MediaStore.Audio.Media.TITLE};
audioCursor = getContentResolver().query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, proj,
MediaStore.Audio.Media.IS_MUSIC, null,
MediaStore.Audio.Media.TITLE + " ASC");
count = audioCursor.getCount();
audioCursor.moveToPosition(position);
int column_index = audioCursor.getColumnIndex(MediaStore.Audio.Media.DATA);
String path = audioCursor.getString(column_index);
startAudioPlayer(path);
playing=true;
if(playerActive)
sendBool(playing, "playing");
}else{
startAudioPlayer(action);
playing=true;
if(playerActive)
sendBool(playing, "playing");
}
action=null;
break;
case MSG_SET_BOOLEAN_VALUE:
pause=msg.getData().getBoolean("pause");
play=msg.getData().getBoolean("play");
stop=msg.getData().getBoolean("stop");
next=msg.getData().getBoolean("next");
back=msg.getData().getBoolean("back");
playerActive=msg.getData().getBoolean("playerActive");
if(pause){
mp.pause();
play=false;
playing=false;
sendBool(playing, "playing");
pause=false;
}
if(play){
pause=false;
mp.start();
playing=true;
sendBool(playing, "playing");
play=false;
}
default:
super.handleMessage(msg);
}
}
}
private void sendInt(int intvaluetosend) {
for (int i=mClients.size()-1; i>=0; i--) {
try {
Bundle b = new Bundle();
b.putInt("int1", intvaluetosend);
Message msg = Message.obtain(null, MSG_SET_INT_VALUE);
msg.setData(b);
mClients.get(i).send(msg);
} catch (RemoteException e) {
mClients.remove(i);
Log.d(TAG, "Int not send..."+e.getMessage());
}
}
}
private void sendString(String stringtosend) {
for (int i=mClients.size()-1; i>=0; i--) {
try {
Bundle b = new Bundle();
b.putString("str1", stringtosend);
Message msg = Message.obtain(null, MSG_SET_STRING_VALUE);
msg.setData(b);
mClients.get(i).send(msg);
} catch (RemoteException e) {
mClients.remove(i);
Log.d(TAG, "String not send..." +e.getMessage());
}
}
}
private void sendBool(boolean booltosend, String name) {
for (int i=mClients.size()-1; i>=0; i--) {
try {
Bundle b = new Bundle();
b.putBoolean(name, booltosend);
Message msg = Message.obtain(null, MSG_SET_BOOLEAN_VALUE);
msg.setData(b);
mClients.get(i).send(msg);
} catch (RemoteException e) {
mClients.remove(i);
Log.d(TAG, "Bool not send..." +e.getMessage());
}
}
}
#Override
public void onCreate() {
super.onCreate();
showNotification();
isRunning=true;
}
private void showNotification() {
nm = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
CharSequence text = getText(R.string.maintit);
Notification notification = new Notification(R.drawable.icon, text, System.currentTimeMillis());
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, Player.class), 0);
notification.setLatestEventInfo(this, getText(R.string.app_name), text, contentIntent);
nm.notify(R.string.app_name, notification);
}
#Override
public void onDestroy() {
//REMEMBER TO SAVE DATA!
if(mp.isPlaying())
mp.stop();
mp.release();
isRunning=false;
audioCursor.close();
nm.cancel(R.string.app_name);
super.onDestroy();
}
public static boolean isRunning()
{
return isRunning;
}
public void startAudioPlayer(String path){
try {
if(mp.isPlaying())
mp.reset();
mp.setDataSource(path);
} catch (IllegalArgumentException e) {
e.printStackTrace();
Log.d(TAG,e.getMessage());
} catch (IllegalStateException e) {
e.printStackTrace();
Log.d(TAG,e.getMessage());
} catch (IOException e) {
e.printStackTrace();
Log.d(TAG,e.getMessage());
}
try {
mp.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
Log.d(TAG,e.getMessage());
} catch (IOException e) {
e.printStackTrace();
Log.d(TAG,e.getMessage());
}
mp.start();
}
}
I hope someone can help, im getting very frustrated with this! Also, Im pretty sure there is no problem with the media player, I tested it before without the service... the cursors also work properly... Thing is... Do I need to necessarily call the service from the GUI for it to play the music?? What am I doing wrong?
EDIT: The website wont allow me to answer my own question so I post the solution here:
Ok, finally found a solution!
I read that the interaction with the service is only available once the onCreate method has finished... So, I added a Timer and filled it with the methods I needed to run:
new Timer().schedule(new TimerTask(){
public void run(){
sendBoolToService(playerActive, "playerActive");
sendIntToService(position);
sendStringToService(action);
}
}, 1000);
AND VOILA! It works! :D Hope its useful to someone!
What you need to do is to move the code in onCreate() which is dependent on the service being available to your onServiceConnected() method in your ServiceConnection implementation:
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
mService = new Messenger(service);
Toast.makeText(getApplicationContext(), "ATTACHED!", Toast.LENGTH_LONG).show();
try {
Message msg = Message.obtain(null, Background.MSG_REGISTER_CLIENT);
msg.replyTo = mMessenger;
mService.send(msg);
sendBoolToService(playerActive, "playerActive");
sendIntToService(position);
sendStringToService(action);
} catch (RemoteException e) {
Toast.makeText(getApplicationContext(), "Connection failed!", Toast.LENGTH_LONG).show();
}
}
public void onServiceDisconnected(ComponentName className) {
mService = null;
Toast.makeText(getApplicationContext(), "UNATTACHED!", Toast.LENGTH_LONG).show();
}
};
I would also look at your service implementation as I cannot understand why you are calling mService = new Messenger(service). Your IBinder instance should provide you with a mechanism for obtaining a reference to your service instance.
In my case, my issue was using android:process attribute for <service> element within Android Manifest, which is supposed to improve performance, but in reallity, maybe it does once the service is running, but it takes a very long while to reach onCreate() (and so also to reach onBind()). For me it was taking minutes. Now Apps and services run smooth and as expected.
I now this a very old question, but showing your Manifest file here makes sense.
More info:
https://developer.android.com/guide/topics/manifest/service-element