I'm creating an app that plays .wav files by audiotrack class in static mode, but i can't figure out how to skip the wave header, here is the code i've done so for, i cant see whats wrong with it! anyone knows how to skip the header?
Thanks!
public class MainActivity extends ActionBarActivity {
AudioTrack player;
int minBufferSize = 200000;
int waveHeader = 44;
byte[] buffer = new byte[minBufferSize -waveHeader];
InputStream is;
public TextView text;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_main);
player = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT, minBufferSize, AudioTrack.MODE_STATIC);
is = getResources().openRawResource(R.raw.crash);
try {is.read(buffer, waveHeader, minBufferSize);} catch (IOException e) {e.printStackTrace();}
try {is.close();} catch (IOException e) {e.printStackTrace();}
player.write(buffer, 0, minBufferSize);
Button button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
playDrums();
}});
}
public void playDrums(){
player.play();
}
}
As indicated in read documentation:
The first byte read is stored into element b[off], the next one into b[off+1], and so on. The number of bytes read is, at most, equal to len. Let k be the number of bytes actually read; these bytes will be stored in elements b[off] through b[off+k-1], leaving elements b[off+k] through b[off+len-1] unaffected.
In other words the parameter off does not skip those bytes from the input stream, but instead stores them with an offset in the provided array.
To skip bytes from the input, you can either use skip:
try {is.skip(waveHeader);} catch (IOException e) {e.printStackTrace();}
try {is.read(buffer, 0, minBufferSize);} catch (IOException e) {e.printStackTrace();}
Or read the wave header in another buffer:
byte[] header = new byte[waveHeader];
try {is.read(header);} catch (IOException e) {e.printStackTrace();}
try {is.read(buffer, 0, minBufferSize);} catch (IOException e) {e.printStackTrace();}
After all you probably need the wave header in order to properly interpret the data (eg. is the data 1 or 2 bytes per sample, sampling rate, number of channels, ...)
Related
When I navigate to a page in the app, I expect the text from the text file to be displayed but it isn't. Am I missing something?
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_content);
Button backButton = findViewById(R.id.button_back);
Button selectAnotherButton = findViewById(R.id.button_select_another);
TextView contentText = findViewById(R.id.content_text);
String text = "";
try {
// file to inputstream
InputStream input = getAssets().open("jokes.txt");
int size = input.available();
byte[] buffer = new byte[size];
input.read(buffer);
input.close();
// byte buffer into a string
text = new String(buffer);
} catch (Exception e) {
System.out.println(e);
}
contentText.setText(text);
}
The code above is fine, it works as expected. The reason the text could not be seen is because there was a textview layout overlapping the file text text view layout so I couldn't see the text
contentText.invalidate();
contentText.requestLayout();
So I'm trying to make my first ever Android app. It's just a simple tally counter for now but I've come across a weird bug.
You see, I've got a simple save and load function, an increment, decrement and reset button. and a TextView that displays the value all together (see below).
Now when I increment the value up to say 10 and close the app, it saves as it should and when I open the app again, it does come back as 10. However, when I then increment up to say 30 or 100, close and restart the value does not stick and comes out as either -1 or a value that is completely different.
What could be happening?
MainActivity.java
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
int value;
TextView textView_value;
final String filename = "tallyCountPlus";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loadValue(filename);
textView_value = (TextView) findviewById(R.id.textView_value);
textView_value.setText(Integer.toString(value));
}
/** Called when the user presses the increment button */
public void incValue(View view) {
value++;
textView_value.setText(Integer.toString(value));
}
/** Called when the user presses the decrement button */
public void decValue(View view) {
if (value > 0) {
value--;
}
textView_value.setText(Integer.toString(value));
}
/** Called when the user presses the reset button */
public void resetValue(View view) {
value = 0;
textView_value.setText(Integer.setString(value));
}
#Override
public void onPause() {
super.onPause();
saveValue(filename, Context.MODE_PRIVATE);
}
#Override
public void onResume() {
super.onResume();
loadValue(filename);
textView_value.setText(Integer.toString(value));
}
public void onDestroy() {
super.onDestroy();
saveValue(filename, Context.MODE_PRIVATE);
}
private void loadValue(String name) {
try {
FileInputStream fis = openFileInput(name);
value = fis.read();
fis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void saveValue(String name, int context) {
try {
FileOutputStream fos = openFileOutput(name, context);
fos.write(value);
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Anyone know what my problem could be?
Thanks.
Jamie.
EDIT:
So I think I've fixed the bug by doing:
private void loadValue(String filename) {
/* this is wrapped in a try-catch statement */
FileInputStream fis = openFileInput(name);
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
StringBuilder = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
}
value = Integer.parseInt(sb.toString());
fis.close() /* Not sure if this is actually neccessary? */
if (value == -1) {
value = 0;
}
}
private void saveValue(String name) {
/* This is also wrapped in a try-catch statement */
FileOutputStream fos = openFileOutput(name, Context.MODE_PRIVATE);
String data = Integer.toString(value);
fos.write(data.getBytes());
fos.close();
}
And after putting in a couple of values, it seems to work fine. However, I'm unsure as to whether it is appending or deleting the previous value and replacing it... I'd rather the latter to prevent the save file from getting too big.
onDestroy() is not dependable. Just stick with onPause(). Also, in general, for the methods that handle events when the activity is "going away", you should call the super method after your own code, to ensure your custom code can still execute.
Other things to check might be:
Is the method that saves the output replacing the previous file, or just appending to it?
Are you properly loading and saving each time?
If the file is properly loaded, is the value making it into the TextView? You might need to construct an anonymous Runnable that ensures that the TextView is updated by the main (UI) thread.
Sprinkle log statements liberally throughout the code to keep track of what the tally is, what you get out of the file, etc.
When diagnosing file issues, it helps to test on an emulator, which gives you root access to the device storage.
You need to modify loadValue() method. You are assigning fis.read() to value which returns next byte or -1 if EOF reached.
private void loadValue(String name) {
try {
FileInputStream in = openFileInput(name);
InputStreamReader inputStreamReader = new InputStreamReader(in);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
StringBuilder sb = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
sb.append(line);
}
value = Integer.parseInt(sb.toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Using various tutorials, I have managed to connect my Android phone to a HC-05 bluetooth module connected to an Arduino. What I'm trying to do is have 5 Buttons set up that will transmit a unique integer per button only when the button is held down, otherwise they will send a "0" when the button is released. ergo BUTTON1 sends a "1" when pressed and "0" when released, BUTTON2 sens a "2" when pressed and a "0" when released. Currently, I cannot figure out how to send ANY data over the connection. From reading and watching various tutorials I've gained a small understanding but seem to be missing something.
Towards the bottom of my code in the public void run(), i have set up an OnClickListener for one of my buttons to try to send...well something once its pressed just to see if I can send SOMETHING useful to the Arduino.
Here is where I have my OnClickListener. I believe I should be sending "T" to the Arduino.
pUpBtn.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v) {
String testr="T:";
byte[] msgBuffer = testr.getBytes();
try {
mmOutStream.write(msgBuffer);
} catch (IOException e) {
e.printStackTrace();
}
}
});
First
Basically as per your requirement you can not use onClickListner instead use onTouchListner
Example
button.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN) {
//send integer value here.(pressed)
} else if (event.getAction() == MotionEvent.ACTION_UP) {
//Send zero here.(released)
}
}
};
here is a sample code for sending and receiving data from bluetoothSPP
this method is to connect bluetooth device to remote device
private void connectToDevice(BluetoothDevice mBTDevice) {
try {
SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
mBtSocket = mBTDevice.createRfcommSocketToServiceRecord(SPP_UUID);
mBtSocket.connect();
} catch (IOException e) {
Log.d("connectBT", "while connecting device");
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
use this for sending bytes.
public void send(String data) {
byte[] buffer = data.getBytes();
try {
mOutputStream = mBtSocket.getOutputStream();
mOutputStream.write(buffer);
Log.d("message", data + " sent");
} catch (IOException e) {
e.printStackTrace();
}
}
use this function for sending Integers
public void send() {
byte[] buffer = new bytes[size];
buffer[0]=(byte)'1';//prepare data like this
..
..
try {
mOutputStream = mBtSocket.getOutputStream();
mOutputStream.write(buffer);
Log.d("message", " sent");
} catch (IOException e) {
e.printStackTrace();
}
}
Hope this helps :)
I'm creating a text file with timestamps derived from the result of System.currentTimeMillis(). My algorithm is such:
Create file and record timestamp of creation
Save timestamp each time a button is pressed
Subtract file-creation timestamp from button-press timestamp
Write result to the file
For some odd reason, the timestamp of the file creation is usually greater (younger, more recent) than the timestamp of the button presses, which always happen AFTER the file was created. This results in a negative value being returned from step 3.
What is causing this?
FileCreationMenu.java
public class FileCreationMenu extends Fragment {
public Button toggleRecordingButton;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.menu_fragment_calibrator, container, false);
toggleRecordingButton = (Button) v.findViewById(R.id.recordAudioToggle);
toggleRecordingButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
recordAudio = !recordAudio; //toggle audio recording on/off
if (recordAudio==true){
AudioRecorder.createFile(System.currentTimeMillis()); //generate file for new track if record is togged ON
}
}
});
AudioRecorder.java
public static void createFile(long time) { //create file and record creation timeStamp
recordingStartTime = time;
myFile = new File(Environment.getExternalStorageDirectory(), "file.txt"); //save to external storage
try {
myFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void recordNote(long timeStamp){ //record timeStamps of notes
String playedNote = (timeStamp+ "\n" );
try {
fos = new FileOutputStream(myFile, true);
fos.write(playedNote.getBytes());
fos.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void playTrack(String fileName){ //playback Notes
try {
FileInputStream fis = new FileInputStream(myFile.getPath());
BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
String line;
try {
int i =0;
while ((line = reader.readLine()) != null) { //read each line of input file
historicalTime[i] = Long.parseLong(line); //store time current line's note was played
if (i==0){
timeStream[i] = (Long.parseLong(line) - recordingStartTime); //if first note, calculate wait based on file creation time
}
else{
timeStream[i] = (Long.parseLong(line) - historicalTime[i-1]); //otherwise, calculate wait as amount of time note was played after most recent preceding note
}
i++;
}
} catch (IOException e){
e.printStackTrace();
}
for (int i=0; i<noteStream.length; i++){
try {
AudioRecorder.class.wait(timeStream[i]); //wait
//Play Note
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
MainActivity.java
...
public static void noteDetected(){
if (FileCreationMenu.recordAudio == true){
AudioRecorder.recordNote(System.currentTimeMillis());
}
Again, the problem is that recordingStartTime in AudioRecorder.java is often greater than the input parameter "timeStamp" to recordNote from the MainActivity. For example, in a recent debugging session recordingStartTime =1,450,573,093,044 while timeStamp=1,450,565,187,318.
What could be causing this seemingly impossible behavior?
The problem is this line:
myFile.createNewFile();
The JavaDoc for this method says
Atomically creates a new, empty file named by this abstract pathname if and only if a file with this name does not yet exist
So every time you try to start a new recording you are actually reusing the same file (with timestamps from long ago) but record a new recordStartTime.
If you want to remove the old file first you will have to write
myFile.delete();
myFile.createNewFile();
I'm new to java, but a quick learner.
I'm trying make my Android App to take user-input from an EditText, search an Excel column for a matching string, and return the value of (the same row of) another column.
I added a jxl.jar on the build path, and my code seems like it should work. Teaching myself, I am slowly figuring out the debugging. The problem seems to be source android.jar was not found (if i remember correctly). I located it, and now I get "the source attachment does not contain the source for the file instrumentation.class"
This is my first app using excel. Do I need to address the Android Manifest somehow?
Here's my code, just in case, and any help is very appreciated!:
public class Frame_Bore extends Activity {
private String inputFile;
public void setInputFile(String inputFile) {
this.inputFile = "c:/Desktop/AAS Work/PDA Programs/JBDB.xls";
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.framebore);
Button Btn1 = (Button) findViewById(R.id.button1);
final EditText T1 = (EditText) findViewById(R.id.et1);
final EditText T2 = (EditText) findViewById(R.id.et2);
Btn1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
String t1Value = T1.getText().toString();
File inputWorkbook = new File(inputFile);
Workbook w;
String bore = null;
try {
w = Workbook.getWorkbook(inputWorkbook);
Sheet sheet = w.getSheet("Frame-Bore");
int y = 6;
while (y < 200) {
int x = 2;
Cell columnB = sheet.getCell(x, y);
String motorframe = columnB.getContents();
if (motorframe == t1Value) {
Cell columnC = sheet.getCell(x + 1, y);
bore = columnC.getContents();
} else {
y = y + 1;
}
}
} catch (BiffException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
T2.setText("" + bore);
}
}
});
}
You are trying to access c: drive ( "c:/Desktop/AAS Work/PDA Programs/JBDB.xls" ) from your emulator, which is not possible. You need to put your excel file either in the resources folder or in SD card, if you are running it in device.
An Emulator has a virtual SD Card, and its limitations is that it can not direct access any other drive from the computer. However you can do it by making a webservice which will perform operation on behalf of your android application. You need to call this web-service from your android application.
Put the file in assets folder and access it like this:
InputStream is = null;
try {
is = context.getAssets().open("JBDB.xls");
workbook = Workbook.getWorkbook(is);
} catch (IOException e) {
e.printStackTrace();
} catch (BiffException e) {
e.printStackTrace();
}
if(workbook!=null)
sheet = workbook.getSheet("Frame-bore");
context is your main activity context.