I am trying to record an outgoing phone call in my class which extends BroadcastReceiver and I am seeing two failure:
This one appears right after the start recording function -
E/MediaRecorder: start failed: -38
This error appears after I am calling the prepare function -
E/Media_APM :: isCalledPackage return false
I must mention that when I run it on the simulator I do not see those errors (but you can't test a phone call recording on a simulator), I only see those error when I run the app on Samsung Galaxy 8 (with Android Pie installed) and Samsung Note 20 (with Android Pie installed).
When I run it on Xiaomi Mi A9 (With Android Q installed) it does not fail but also doesn't record anything - I see the audio file, it's in the right length but it's empty).
This is my code:
public class CallBr extends BroadcastReceiver {
Bundle bundle;
String state;
#RequiresApi(api = Build.VERSION_CODES.O)
#Override
public void onReceive(Context context, Intent intent) {
if (Objects.equals(intent.getAction(), ACTION_IN)) {
if ((bundle = intent.getExtras()) != null) {
state = bundle.getString(TelephonyManager.EXTRA_STATE);
if (state != null && state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
if (shouldStartRecording) {
recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION);
recorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
File callAudioFile = null;
try {
File downloadsDir = context.getApplicationContext().getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);
callAudioFile = File.createTempFile("deTuCelRecord", ".amr", downloadsDir);
} catch (IOException e) {
e.printStackTrace();
}
assert callAudioFile != null;
audioFilePath = callAudioFile.getAbsolutePath();
recorder.setOutputFile(audioFilePath);
try {
recorder.setOnErrorListener(new MediaRecorder.OnErrorListener() {
#Override
public void onError(MediaRecorder mr, int what, int extra) {
Log.e("MediaRecorder", "MediaRecorder error " + what + " " + extra);
}
});
recorder.prepare();
} catch (Error e) {
Log.e("RecPrep", "So there was an error ...");
e.printStackTrace();
Log.d("RecPrep", "Did you get what that error was?");
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
Log.e("RecPrep", "startRecording: ", e);
}
recorder.start();
recordStarted = true;
shouldStartRecording = false;
}
shouldStartRecording = true;
}
if (state != null && state.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
if (recordStarted) {
recorder.stop();
recorder.release();
convertToAmr();
compareAudioFiles(context);
recordStarted = false;
}
}
}
}
}
}
Related
I am trying Data send with Bluetooth intent service with these codes but i can not send message to device. I am debugging this code but DataSend class elements seems null. How can i fix the problem or how can i write correctly sending message code with using intent service ?
I am calling the fragment this way:
final Intent sendData = new Intent(getActivity(),DataSend.class);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String s = editText.getText().toString();
sendData.putExtra("test",s);
}
});
This is my DataSend service code:
public class DataSend extends IntentService{
private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
private static final String TAG = "DataTransmissionService";
private BluetoothAdapter btAdapter = null;
private BluetoothSocket btSocket = null;
private OutputStream outStream = null;
private BluetoothDevice device = null;
private Log log;
public DataSend() {
super("DataSend");
}
#Override
protected void onHandleIntent(Intent intent) {
cleanup();
if (intent != null){
btAdapter = BluetoothAdapter.getDefaultAdapter();
String pairedDeviceAddress = "38:1B:4B:98:E7:ED";
try {
log.d(TAG, pairedDeviceAddress);
device = btAdapter.getRemoteDevice(pairedDeviceAddress);
log.d(TAG, "Device bond state : " + device.getBondState());
} catch (Exception e) {
log.e(TAG, "Invalid address: " + e.getMessage());
return;
}
try {
btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
log.e(TAG, "Socket creation failed: " + e.getMessage());
return;
}
try {
if (!btSocket.isConnected()) {
btSocket.connect();
log.d(TAG, "Connected");
} else {
log.d(TAG, "Already Connected"); //flow never reaches here for any use case
}
} catch (IOException e) {
log.e(TAG, "btSocket.connect() failed : " + e.getMessage());
return;
}
try {
outStream = btSocket.getOutputStream();
} catch (IOException e) {
log.e(TAG, "Failed to get output stream:" + e.getMessage());
return;
}
sendData("test");
//cleanup(); called in onDestroy()
}
}
private void cleanup(){
try {
if (outStream != null) {
outStream.close();
outStream = null;
}
} catch (Exception e) {
log.e(TAG, "Failed to close output stream : " + e.getMessage());
}
try {
if (btSocket != null) {
btSocket.close();
btSocket = null;
}
}catch (Exception e) {
log.e(TAG, "Failed to close connection : " + e.getMessage());
}
}
private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOException {
if(Build.VERSION.SDK_INT >= 10){
try {
final Method m = device.getClass().getMethod("createInsecureRfcommSocketToServiceRecord", new Class[] { UUID.class });
return (BluetoothSocket) m.invoke(device, MY_UUID);
} catch (Exception e) {
log.e(TAG, "Could not create Insecure RFComm Connection",e);
}
}
return device.createRfcommSocketToServiceRecord(MY_UUID);
}
private void sendData(String message) {
byte[] msgBuffer = message.getBytes();
log.d(TAG, "Sending : " + message);
try {
outStream.write(msgBuffer);
} catch (IOException e) {
log.e(TAG, "failed to write " + message);
}
}
}
I would initialize a BluetoothConnection with the device you are connected to, and then send data that way. It would look somewhat like this:
BluetoothConnection connection = new BluetoothConnection(connectedDevice);
public void sendData(){
String s = editText.getText().toString();
byte[] b = s.getBytes();
connection.write(b);
//System.out.println("Bytes Sent");
}// end sendData
Do you call startService(sendData); in order to start the Bluetooth send service? It seems that you are just creating the intent and filling it with data but not starting it.
I had this error on my VoiSip Application
E/AudioRecord: AudioFlinger could not create record track, status: -1
E/AudioGroup: cannot initialize audio device
This error occurs after I'm trying to make call to another sip address
Here have 2 java class(WalkieTalkieActivity.java & IncomingCallReceiver.java)
WalkieTalkieActivity.java
public class WalkieTalkieActivity extends Activity implements View.OnTouchListener {
public IncomingCallReceiver callReceiver;
public SipManager mSipManager = null;
public SipProfile mSipProfile = null;
public SipAudioCall call = null;
TextView tv;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_walkie_talkie);
ToggleButton pushToTalkButton = (ToggleButton) findViewById(R.id.pushToTalk);
pushToTalkButton.setOnTouchListener(this);
IntentFilter filter = new IntentFilter();
filter.addAction("android.SipDemo.INCOMING_CALL");
callReceiver = new IncomingCallReceiver();
this.registerReceiver(callReceiver, filter);
if (mSipManager == null) {
mSipManager = SipManager.newInstance(this);
}
tv = (TextView)findViewById(R.id.textView);
}
#Override
public void onStart() {
super.onStart();
// When we get back from the preference setting Activity, assume
// settings have changed, and re-login with new auth info.
initializeManager();
}
#Override
public void onDestroy() {
super.onDestroy();
if (call != null) {
call.close();
}
closeLocalProfile();
if (callReceiver != null) {
this.unregisterReceiver(callReceiver);
}
}
public void closeLocalProfile() {
if (mSipManager == null) {
return;
}
try {
if (mSipProfile != null) {
mSipManager.close(mSipProfile.getUriString());
}
} catch (Exception ee) {
Log.d("onDestroy", "Failed to close local profile.", ee);
}
}
public void initializeManager() {
if(mSipManager == null) {
mSipManager = SipManager.newInstance(this);
}
initializeLocalProfile();
}
private void initializeLocalProfile() {
String domain = "mydomain";
String username = "myusername";
String password = "mypassword";
try {
SipProfile.Builder builder = new SipProfile.Builder(username, domain);
builder.setPassword(password);
mSipProfile = builder.build();
if (mSipProfile == null){
Log.e("error cukimai", "null");
}else{
Log.e("error cukimai", "not null");
}
Intent i = new Intent();
i.setAction("android.SipDemo.INCOMING_CALL");
PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, Intent.FILL_IN_DATA);
mSipManager.open(mSipProfile, pi, null);
mSipManager.setRegistrationListener(mSipProfile.getUriString(), new SipRegistrationListener() {
public void onRegistering(String localProfileUri) {
updateStatus("Registering with SIP Server...");
Log.e("process","Registering with SIP Server...");
}
public void onRegistrationDone(String localProfileUri, long expiryTime) {
updateStatus("Ready");
Log.e("process","ready");
}
public void onRegistrationFailed(String localProfileUri, int errorCode,
String errorMessage) {
updateStatus("Registration failed. Please check settings.");
Log.e("process","Registration failed. Please check settings.");
}
});
Log.e("process","stop");
} catch (SipException e) {
e.printStackTrace();
Log.e("error cukimai", "cuk cuk");
} catch (ParseException e) {
e.printStackTrace();
Log.e("error cukimai", "cuk");
}
}
public void updateStatus(final String st){
this.runOnUiThread(new Runnable() {
public void run() {
tv.setText(st);
}
});
}
public void updateStatus(SipAudioCall call) {
String useName = call.getPeerProfile().getDisplayName();
if(useName == null) {
useName = call.getPeerProfile().getUserName();
}
updateStatus(useName + "#" + call.getPeerProfile().getSipDomain());
}
public void callAct(View view) {
Toast.makeText(this, "about to make call", Toast.LENGTH_LONG).show();
makeCall();
}
public void makeCall(){
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
// Much of the client's interaction with the SIP Stack will
// happen via listeners. Even making an outgoing call, don't
// forget to set up a listener to set things up once the call is established.
#Override
public void onCallEstablished(SipAudioCall call) {
call.startAudio();
call.setSpeakerMode(true);
call.toggleMute();
updateStatus(call);
}
#Override
public void onCallEnded(SipAudioCall call) {
updateStatus("Ready.");
}
};
call = mSipManager.makeAudioCall(mSipProfile.getUriString(), "sip:destination#domain", listener, 30);
Log.e("make call", "true");
start();
}catch (Exception e){
Log.i("error", "Error when trying to close manager.", e);
if (mSipProfile != null) {
try {
mSipManager.close(mSipProfile.getUriString());
} catch (Exception ee) {
Log.i("error", "Error when trying to close manager.", ee);
ee.printStackTrace();
}
}
if (call != null) {
call.close();
}
}
}
#Override
public boolean onTouch(View view, MotionEvent event) {
if (call == null) {
return false;
} else if (event.getAction() == MotionEvent.ACTION_DOWN && call != null && call.isMuted()) {
call.toggleMute();
} else if (event.getAction() == MotionEvent.ACTION_UP && !call.isMuted()) {
call.toggleMute();
}
return false;
}
final MediaRecorder recorder = new MediaRecorder();
final String path;
/**
* Creates a new audio recording at the given path (relative to root of SD card).
*/
public WalkieTalkieActivity(String path) {
this.path = sanitizePath(path);
}
private String sanitizePath(String path) {
if (!path.startsWith("/")) {
path = "/" + path;
}
if (!path.contains(".")) {
path += ".3gp";
}
return Environment.getExternalStorageDirectory().getAbsolutePath() + path;
}
/**
* Starts a new recording.
*/
public void start() throws IOException {
String state = android.os.Environment.getExternalStorageState();
if(!state.equals(android.os.Environment.MEDIA_MOUNTED)) {
throw new IOException("SD Card is not mounted. It is " + state + ".");
}
// make sure the directory we plan to store the recording in exists
File directory = new File(path).getParentFile();
if (!directory.exists() && !directory.mkdirs()) {
throw new IOException("Path to file could not be created.");
}
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(path);
recorder.prepare();
recorder.start();
}
/**
* Stops a recording that has been previously started.
*/
public void stop() throws IOException {
recorder.stop();
recorder.release();
}
}
IncomingCallReceiver.java
public class IncomingCallReceiver extends BroadcastReceiver {
/**
* Processes the incoming call, answers it, and hands it over to the
* WalkieTalkieActivity.
* #param context The context under which the receiver is running.
* #param intent The intent being received.
*/
#Override
public void onReceive(Context context, Intent intent) {
SipAudioCall incomingCall = null;
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
#Override
public void onRinging(SipAudioCall call, SipProfile caller) {
try {
call.answerCall(30);
} catch (Exception e) {
e.printStackTrace();
}
}
};
WalkieTalkieActivity wtActivity = (WalkieTalkieActivity) context;
incomingCall = wtActivity.mSipManager.takeAudioCall(intent, listener);
incomingCall.answerCall(30);
incomingCall.startAudio();
incomingCall.setSpeakerMode(true);
if(incomingCall.isMuted()) {
incomingCall.toggleMute();
}
wtActivity.call = incomingCall;
wtActivity.updateStatus(incomingCall);
} catch (Exception e) {
if (incomingCall != null) {
incomingCall.close();
}
}
}
}
I'm really new on Sip and Voip Implementing in Android Studio. I got this code from google source code.
I believe this error occurs because of the use of hardware (audio). However I have been searching on google for almost 1 week and not giving results. Can someone help me?
I had same problem but when i changed targetSdkVersion to 12 in build.gradel its fixed.
and this answer helped me to fixed problem .
You must choose the BufferSize when you want to record or call in app. For example:
int bufferSize = AudioRecord.getMinBufferSize(rate, channelConfig, audioFormat);
if (bufferSize > 0 && bufferSize <= 256){
bufferSize = 256;
}else if (bufferSize > 256 && bufferSize <= 512){
bufferSize = 512;
}else if (bufferSize > 512 && bufferSize <= 1024){
bufferSize = 1024;
}else if (bufferSize > 1024 && bufferSize <= 2048){
bufferSize = 2048;
}else if (bufferSize > 2048 && bufferSize <= 4096){
bufferSize = 4096;
}else if (bufferSize > 4096 && bufferSize <= 8192){
bufferSize = 8192;
}else if (bufferSize > 8192 && bufferSize <= 16384){
bufferSize = 16384;
}else{
bufferSize = AudioRecord.getMinBufferSize(rate, channelConfig, audioFormat);
}
Hi I am stuck while i was trying to control 8x8 led matrix by cascading two 74hc595 shift registers. I had build the circuit and the program, which I am including here. It's actually giving me the right output. But the major problem is visible flickering. Can somebody guide me what can i do to remove the flickering?
public class MainActivity extends Activity {
private static final String SR_SRCLK_PIN = "BCM27"; //clock pins shcp
private static final String SR_RCLK_PIN = "BCM18"; //latch pin stcp
private static final String SR_SDI_PIN = "BCM17"; //data pin
private static final String TAG = "MAT21";
private Gpio mRCLK;
private Gpio mSRCLK;
private Gpio mSDI;
private int charSeq=0;
int data[]=
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //NULL
0x00,0x00,0x3C,0x42,0x42,0x3C,0x00,0x00, //0
0x00,0x00,0x00,0x44,0x7E,0x40,0x00,0x00, //1
0x00,0x00,0x44,0x62,0x52,0x4C,0x00,0x00, //2
0x00,0x00,0x78,0x14,0x12,0x14,0x78,0x00, //A
0x00,0x00,0x60,0x90,0x90,0xFE,0x00,0x00, //d
0x00,0x00,0x1C,0x2A,0x2A,0x2A,0x24,0x00, //e
0x00,0x00,0x7E,0x12,0x12,0x0C,0x00,0x00, //p
0x00,0x00,0x08,0x7E,0x88,0x40,0x00,0x00, //t
0x3C,0x42,0x95,0xB1,0xB1,0x95,0x42,0x3C, //:)
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PeripheralManagerService pms = new PeripheralManagerService();
try {
mRCLK = pms.openGpio(SR_RCLK_PIN);
mRCLK.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
mSRCLK = pms.openGpio(SR_SRCLK_PIN);
mSRCLK.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
mSDI = pms.openGpio(SR_SDI_PIN);
mSDI.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
} catch (IOException e) {
Log.e(TAG, "Error on PeripheralIO API", e);
}
try {
thread.start();
while (true){
Thread.sleep(2000);
charSeq++;
if(charSeq==10){
charSeq=0;
}
}
} catch (Exception sd) {
}
}
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
while (true) {
for (int rowNum = 0; rowNum < 8; rowNum++) {
mRCLK.setValue(false);
shiftOut(data[(charSeq * 8) + rowNum],rowNum);
mRCLK.setValue(true);
}
}
}catch (Exception ex){
}
}
});
#Override
protected void onDestroy() {
super.onDestroy();
// Clean all resources
if (mSDI != null) {
try {
mSDI.setValue(false);
mSDI.close();
} catch (IOException e) {
Log.e(TAG, "Error on PeripheralIO API", e);
}
}
if (mRCLK != null) {
try {
mRCLK.setValue(false);
mRCLK.close();
} catch (IOException e) {
Log.e(TAG, "Error on PeripheralIO API", e);
}
}
if (mSRCLK != null) {
try {
mSRCLK.setValue(false);
mSRCLK.close();
} catch (IOException e) {
Log.e(TAG, "Error on PeripheralIO API", e);
}
}
}
void shiftOut(int data, int rowNum) {
try {
for (int i = 7; i >= 0; i--) {
mSRCLK.setValue(false);
mSDI.setValue((((data >> i) & 1) == 0));
mSRCLK.setValue(true);
}
for (int i = 0; i <8; i++) {
mSRCLK.setValue(false);
mSDI.setValue(i==rowNum?true:false);
mSRCLK.setValue(true);
}
} catch (Exception sd) {
}
}
}
Schemetic Diagram
It's not entirely clear from your question what clock frequency you need to achieve to drive your matrix display properly, but regardless it's unlikely you will be able to get there bit-banging the GPIO in this fashion. The flickering you see is probably because the I/O is not toggling fast enough in your code.
I would recommend moving to an external hardware controller for your display (something like the MAX7219, for example) that you can control over a serial port like I2C or SPI.
I have approximately 6236 Audio files. What I am doing is that I am getting int values from the Database and setting them in loop. For Example after query I got 1 in 'a' and 7 in 'b'. Now I tried to used them in loop like for(int i=a;i<=b;i++) and passed it in my Path to play Audios one by one but 7 audios playing at a time. I am setting values dynamically from database in loop.What I want to do is to just play them one by one but I am stuck.
Here is my Code:
DatabaseAccess db=DatabaseAccess.getInstance(getApplicationContext());
db.open();
mycursor= db.getblindfirst(newid);
scursor= db.getblindlast(newid);
scursor.moveToFirst();
mycursor.moveToFirst();
a= mycursor.getInt(0);
b=scursor.getInt(0);
for (int i=a;i<=b;i++){
try {
mPlayer.setDataSource("/mnt/sdcard/audio/aya(" + i + ").mp3");
mPlayer.prepare();
} catch (Exception e) {
e.printStackTrace();
}
mPlayer.start();
}
db.close();
}
That is because you are playing all the files at once. You should put the code that should run when the music is completed in the OnCompletionListener.
DatabaseAccess db=DatabaseAccess.getInstance(getApplicationContext());
db.open();
mycursor= db.getblindfirst(newid);
scursor= db.getblindlast(newid);
scursor.moveToFirst();
mycursor.moveToFirst();
a= mycursor.getInt(0);
b=scursor.getInt(0);
mPlayer = new MediaPlayer();
try {
mPlayer.setDataSource("/mnt/sdcard/audio/aya(" + a + ").mp3");
mPlayer.prepare();
} catch (Exception e) {
e.printStackTrace();
}
mPlayer.start();
a++;
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
if (a!=b) {
if(mPlayer != null) {
if(mPlayer.isPlaying()) {
mPlayer.stop();
}
mPlayer.reset();
}
try {
mPlayer.setDataSource("/mnt/sdcard/audio/aya(" + a + ").mp3");
mPlayer.prepare();
} catch (Exception e) {
e.printStackTrace();
}
mPlayer.start();
a++;
}
}
});
db.close();
}
I have an android tablet in which inbuilt printer and scanner are present.
Now my task is to print a gate pass. Gate pass layout contains many text fields and edit text. I need my tablets printer to print this whole page.I need the code in java.
I would like to know if printing can be done directly without any PDF or Bluetooth. Because I can print only a single field using the print button as I have all the sdk regarding that printer. Now, my issue is that I want to print the whole layout.
try this code hope it help you
openButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
findBT();
openBT();
} catch (IOException ex) {
ex.printStackTrace();
}
}});
Find BT Method
// this will find a bluetooth printer device
void findBT() {try {
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if(mBluetoothAdapter == null) {
myLabel.setText("No bluetooth adapter available");
}
if(!mBluetoothAdapter.isEnabled()) {
Intent enableBluetooth = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBluetooth, 0);
}
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
if(pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
// RPP300 is the name of the bluetooth printer device
// we got this name from the list of paired devices
if (device.getName().equals("RPP300")) {
mmDevice = device;
break;
}
}
}
myLabel.setText("Bluetooth device found.");
}catch(Exception e){
e.printStackTrace();
}}
Open BT method
// tries to open a connection to the bluetooth printer device
void openBT() throws IOException {
try {// Standard SerialPortService ID
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
mmSocket = mmDevice.createRfcommSocketToServiceRecord(uuid);
mmSocket.connect();
mmOutputStream = mmSocket.getOutputStream();
mmInputStream = mmSocket.getInputStream();
beginListenForData();
myLabel.setText("Bluetooth Opened");
} catch (Exception e) {
e.printStackTrace();
}}
We need beginListenForData() method so that openBT() method will work.
after opening a connection to bluetooth printer device,
we have to listen and check if a data were sent to be printed.
void beginListenForData() {
try {final Handler handler = new Handler();
// this is the ASCII code for a newline character
final byte delimiter = 10;
stopWorker = false;
readBufferPosition = 0;
readBuffer = new byte[1024];
workerThread = new Thread(new Runnable() {
public void run() {
while (!Thread.currentThread().isInterrupted() && !stopWorker) {
try {
int bytesAvailable = mmInputStream.available();
if (bytesAvailable > 0) {
byte[] packetBytes = new byte[bytesAvailable];
mmInputStream.read(packetBytes);
for (int i = 0; i < bytesAvailable; i++) {
byte b = packetBytes[i];
if (b == delimiter) {
byte[] encodedBytes = new byte[readBufferPosition];
System.arraycopy(
readBuffer, 0,
encodedBytes, 0,
encodedBytes.length
);
// specify US-ASCII encoding
final String data = new String(encodedBytes, "US-ASCII");
readBufferPosition = 0;
// tell the user data were sent to bluetooth printer device
handler.post(new Runnable() {
public void run() {
myLabel.setText(data);
}
});
} else {
readBuffer[readBufferPosition++] = b;
}
}
}
} catch (IOException ex) {
stopWorker = true;
}
}
}
});
workerThread.start();
} catch (Exception e) {
e.printStackTrace();
}}
We will make an onClickListener for the “Send” button. Put the following code after the onClickListener of the “Open” button, inside onCreate() method.
// send data typed by the user to be printed
sendButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
sendData();
} catch (IOException ex) {
ex.printStackTrace();
}
}});
sendData() method is needed so that the “Open” button will work. Put it below the beginListenForData() method code block.
// this will send text data to be printed by the bluetooth printer
void sendData() throws IOException {try {
// the text typed by the user
String msg = myTextbox.getText().toString();
msg += "\n";
mmOutputStream.write(msg.getBytes());
// tell the user data were sent
myLabel.setText("Data sent.");
} catch (Exception e) {
e.printStackTrace();
}}
We will code an onClickListener for the “close” button so we can close the connection to Bluetooth printer and save battery. Put the following code after the onClickListener of the “Send” button, inside onCreate() method.
// close bluetooth connection
closeButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
closeBT();
} catch (IOException ex) {
ex.printStackTrace();
}
}});
closeBT() method in Step 12 will not work without the following code. Put it below the sendData() method code block.
// close the connection to bluetooth printer.
void closeBT() throws IOException {
try {
stopWorker = true;
mmOutputStream.close();
mmInputStream.close();
mmSocket.close();
myLabel.setText("Bluetooth Closed");
} catch (Exception e) {
e.printStackTrace();
}}
Make sure the BLUETOOTH permission was added to your manifest file. It is located in manifests/AndroidManifest.xml, the code inside should look like the following.
<uses-permission android:name="android.permission.BLUETOOTH" />