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
Related
I`m trying to implement "Change DNS programmatically logic" in my app. Everything working well but when i try to download/update app thru Google play it's doesn't start only progressing without stop. When i stop my service everything working well and i can download/update apps without any problem.
This is my Service:
public class VPNService extends VpnService {
private VpnService.Builder builder = new VpnService.Builder();
private ParcelFileDescriptor fileDescriptor;
private Thread mThread;
private boolean shouldRun = true;
private DatagramChannel tunnel;
public static final String ACTION_CONNECT = VPNService.class.getName() + ".START";
public static final String ACTION_DISCONNECT = VPNService.class.getName() + ".STOP";
#Override
public void onDestroy() {
if (mThread != null) {
mThread.interrupt();
}
super.onDestroy();
}
#Override
public void onCreate() {
super.onCreate();
startForeground(999, new Notification());
}
private void setTunnel(DatagramChannel tunnel) {
this.tunnel = tunnel;
}
private void setFileDescriptor(ParcelFileDescriptor fileDescriptor) {
this.fileDescriptor = fileDescriptor;
}
#Override
public int onStartCommand(final Intent intent, int flags, int startId) {
if (intent != null && ACTION_DISCONNECT.equals(intent.getAction())) {
onDestroy();
return Service.START_NOT_STICKY;
}
mThread = new Thread(() -> {
try {
setFileDescriptor(builder.setSession(VPNService.this.getText(R.string.app_name).toString()).
addAddress("192.168.0.1", 24).addDnsServer("94.155.240.3").addDnsServer("212.50.87.211").establish());
setTunnel(DatagramChannel.open());
tunnel.connect(new InetSocketAddress("127.0.0.1", 8087));
protect(tunnel.socket());
while (shouldRun)
Thread.sleep(100L);
} catch (Exception exception) {
exception.printStackTrace();
} finally {
if (fileDescriptor != null) {
try {
fileDescriptor.close();
setFileDescriptor(null);
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
mThread.start();
return Service.START_STICKY;
}
public static void startVService(Context context) {
VPNService.prepare(context);
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
ContextCompat.startForegroundService(context,new Intent(context, VPNService.class).setAction(ACTION_CONNECT));
else
context.startService(new Intent(context, VPNService.class).setAction(ACTION_CONNECT));
}catch (RuntimeException e){
Log.d("VPNService","Not allowed to start service Intent",e);
}
}
}
You may have to exclude playstore from the vpn.
https://www.reddit.com/r/ProtonVPN/comments/bzh6ir/apps_not_downloadingupdating_via_google_play/
vpnBuilder.addDisallowedApplication(packageName); // where package name is com.android.vending (Play store)
I'm making a OBDII Bluetooth Android app and i'm having some issues sending out commands. I've already made a successfully connection between my mobile device and my OBDII adapter, but when I click on another activity, the Bluetooth connection seems to quit?
When you open up the app you'll see a button that says "Connect Device". When you press that, a ListAdapter will show up with paired Bluetooth devices. Then when you have succesfully connected to the device (OBDII Adapter) it will take you to another layout where there is 3 activities that are 3 different powerplatforms for cars. This is where the problem occurs. For now, I just want to be able to read the voltage from the OBDII. But when I click my button getValue inside one of the 3 activities. I get an logcat error. And I think it's because I haven't initiated my BluetoothHandler properly. I have no idea how to do this.
MainActivity:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
Button b1;
BluetoothAdapter mAdapter;
FragmentHostCallback mHost;
BTHandler btHandler;
private Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case Constants.MESSAGE_STATE_CHANGE:
switch (msg.arg1) {
case BTHandler.STATE_CONNECTED:
//setContentView(R.layout.activity_connected);
Intent intent = new Intent(MainActivity.this, Connected.class);
startActivity(intent);
Toast.makeText(getApplicationContext(), R.string.title_connected_to, Toast.LENGTH_SHORT).show();
Log.v("Log", "Connected");
break;
case BTHandler.STATE_NONE:
Toast.makeText(getApplicationContext(), R.string.title_not_connected, Toast.LENGTH_SHORT).show();
break;
}
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btHandler = new BTHandler(MainActivity.this, mHandler);
b1 = (Button) findViewById(R.id.connect);
b1.setOnClickListener(this);
mAdapter = BluetoothAdapter.getDefaultAdapter();
//init();
if (mAdapter == null) {
Toast.makeText(getApplicationContext(), R.string.device_not_supported, Toast.LENGTH_LONG).show();
finish();
} else {
if (!mAdapter.isEnabled()) {
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, 1);
}
}
//BTHandler btHandler = new BTHandler(MainActivity.this, mHandler);
//btHandler.connect("");
}
public void onClick(View v) {
int id = v.getId();
//String voltage = ("ATRV");
switch (id) {
case R.id.connect:
onConnect(); //Operation
Log.v("Log", "Pressed onClick");
break;
/*case R.id.getValue:
btHandler.write(voltage);
Log.v("Log", "getValue" + voltage);
break;*/
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_CANCELED) {
Toast.makeText(getApplicationContext(), R.string.enable_bluetooth, Toast.LENGTH_SHORT).show();
finish();
}
}
private void onConnect() {
ArrayList deviceStrs = new ArrayList();
final ArrayList<String> devices = new ArrayList();
BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter();
Set pairedDevices = mAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
for (Object device : pairedDevices) {
BluetoothDevice bdevice = (BluetoothDevice) device;
deviceStrs.add(bdevice.getName() + "\n" + bdevice.getAddress());
devices.add(bdevice.getAddress());
}
}
// show list
final AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.select_dialog_singlechoice,
deviceStrs.toArray(new String[deviceStrs.size()]));
alertDialog.setSingleChoiceItems(adapter, -1, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
int position = ((AlertDialog) dialog).getListView().getCheckedItemPosition();
String deviceAddress = devices.get(position);
btHandler.connect(deviceAddress);
//btHandler.write();
}
});
alertDialog.setTitle("Paired devices");
alertDialog.show();
}
BTHandler:
public class BTHandler {
public static final int STATE_NONE = 0; // we're doing nothing
public static final int STATE_CONNECTING = 2; // now initiating an outgoing connection
public static final int STATE_CONNECTED = 3; // now connected to a remote device
final ArrayList<String> devices = new ArrayList();
private final Handler mHandler;
private BluetoothAdapter mAdapter;
private BluetoothDevice device;
private ConnectThread mConnectThread;
private ConnectedThread mConnectedThread;
private BluetoothSocket socket;
private String status;
private int mState;
private boolean connectionStatus = false;
public BTHandler(Context context, Handler handler) { // Konstruktor
mAdapter = BluetoothAdapter.getDefaultAdapter();
mHandler = handler;
}
public void write(String s) {
mConnectedThread.sendRawCommand(s);
Log.v("write", "write");
}
/*
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) {
}
}
*/
public void connect(String deviceAddress) {
mConnectThread = new ConnectThread(deviceAddress);
mConnectThread.start();
}
private void guiHandler(int what, int arg1, String obj) {
Message msg = mHandler.obtainMessage();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.sendToTarget();
}
private class ConnectThread extends Thread {
BluetoothSocket tmp = null;
private BluetoothSocket mmSocket;
public ConnectThread(String deviceAddress) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
device = mAdapter.getRemoteDevice(deviceAddress);
BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothDevice device = mAdapter.getRemoteDevice(deviceAddress);
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
try {
tmp = device.createRfcommSocketToServiceRecord(uuid);
//socket.connect();
//Log.v("connect", "connect");
} catch (IOException e) {
//e.printStackTrace();
//Log.v("exception", "e");
}
mmSocket = tmp;
}
public void run() {
// Cancel discovery because it will slow down the connection
mAdapter.cancelDiscovery();
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes;
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
mmSocket.connect();
Log.v("connect", "connect");
} catch (IOException connectException) {
// Unable to connect; close the socket and get out
try {
mmSocket.close();
Log.v("close", "close");
} catch (IOException closeException) {
}
guiHandler(Constants.TOAST, Constants.SHORT, "Connection Failed");
return;
}
guiHandler(Constants.CONNECTION_STATUS, Constants.STATE_CONNECTED, "");
mConnectedThread = new ConnectedThread(mmSocket);
mConnectedThread.start();
}
}
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
private ObdMultiCommand multiCommand;
public ConnectedThread(BluetoothSocket socket) {
connectionStatus = true;
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
try {
//RPMCommand engineRpmCommand = new RPMCommand();
//SpeedCommand speedCommand = new SpeedCommand();
ModuleVoltageCommand voltageCommand = new ModuleVoltageCommand();
while (!Thread.currentThread().isInterrupted()) {
//engineRpmCommand.run(mmInStream, mmOutStream); //(socket.getInputStream(), socket.getOutputStream());
//speedCommand.run(mmInStream, mmOutStream); //(socket.getInputStream(), socket.getOutputStream());
voltageCommand.run(socket.getInputStream(), socket.getOutputStream());
// TODO handle commands result
//Log.d("Log", "RPM: " + engineRpmCommand.getFormattedResult());
//Log.d("Log", "Speed: " + speedCommand.getFormattedResult());
Log.v("Log", "Voltage: " + voltageCommand.getFormattedResult());
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void run() {
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
OBDcmds();
// Keep listening to the InputStream until an exception occurs
while (connectionStatus) {
sendMultiCommand();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// CALL this to MainActivity
public void sendRawCommand(String command) {
try {
new OdbRawCommand(command);
} catch (Exception e) {
Log.v("sendRawCommand", "e");
}
}
private void OBDcmds() { // execute commands
try {
new EchoOffCommand().run(socket.getInputStream(), socket.getOutputStream());
new LineFeedOffCommand().run(socket.getInputStream(), socket.getOutputStream());
new TimeoutCommand(100).run(socket.getInputStream(), socket.getOutputStream());
new SelectProtocolCommand(ObdProtocols.AUTO).run(socket.getInputStream(), socket.getOutputStream()); //ISO_15765_4_CAN
} catch (Exception e) {
Log.v("OBDcmds", "e");
// handle errors
}
}
/*
// Call this from the main activity to send data to the remote device
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) {
}
}
*/
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
}
}
public void sendMultiCommand() {
try {
// RUN some code here
} catch (Exception e) {
}
}
}
}
SPA: One of the power platforms mentioned before.
public class SPA extends AppCompatActivity implements View.OnClickListener {
Button b2;
BTHandler btHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sp);
b2 = (Button) findViewById(R.id.getValue);
b2.setOnClickListener(this);
}
public void onClick(View v) {
int id = v.getId();
String voltage = ("AT RV");
switch (id) {
case R.id.getValue:
btHandler.write(voltage);
Log.v("Log", "getValue" + voltage);
break;
}
}
}
Logcat:
The reason of the error is here:
BTHandler btHandler;
and you are doing this:
btHandler.write(voltage);
but the object is null referenced....
you need to initialize the BTHandler in the oncreate...
or maybe better:
use a service so you can Bind all the activities to that...
PS:
Note that the BTHandler of the MainActivity is not the same as the one declared in the SPA Class... so although that btHandler is constructed and works in MainActivity doesnt mean it will work in other activities/classes
I got list of numbers and I have to make call foreach number and end it after 10 sec and start the new call.
code is working to make calls but after finish with all list item calling is not stopping its continuesly making calls with first number only?
private void StartCalling()
{
try
{
if(allNumbers.size() != 0)
{
countDown = allNumbers.size();
for (Iterator<String> iter = allNumbers.listIterator(); iter.hasNext(); ) {
final String num = iter.next();
final TelephonyManager tManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
PhoneStateListener phoneStateListener = new PhoneStateListener() {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
if (state == TelephonyManager.CALL_STATE_IDLE) {
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:" + num));
startActivity(callIntent);
}
}
};
tManager.listen(phoneStateListener,PhoneStateListener.LISTEN_CALL_STATE);
}
}else
{
Message.message(CTX,"Not a calling number..");
}
}catch(Exception ex)
{
Message.message(CTX,"" + ex);
}
}
and to end the call after 10 seconds.
public class PhoneCall extends BroadcastReceiver {
CountDownTimer mCountDownTimer;
long countdownPeriod;
long remainingCount;
#Override
public void onReceive(final Context context, Intent intent) {
try {
TelephonyManager tManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
PhoneStateListener phoneStateListener = new PhoneStateListener() {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
if (state == TelephonyManager.CALL_STATE_OFFHOOK) {
countdownPeriod = 10000;
createCountDownTimer(context);
}
}
};
tManager.listen(phoneStateListener,PhoneStateListener.LISTEN_CALL_STATE);
} catch (Exception e) {
e.printStackTrace();
}
}
private void createCountDownTimer(final Context context) {
mCountDownTimer = new CountDownTimer(countdownPeriod, 1000) {
#Override
public void onTick(long millisUntilFinished) {
long l = millisUntilFinished/1000;
countdownPeriod = l;
}
#Override
public void onFinish() {
TelephonyManager tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
Class c = null;
try {
c = Class.forName(tm.getClass().getName());
if(c != null)
{
Method m = tm.getClass().getDeclaredMethod("getITelephony");
m.setAccessible(true);
Object iTelephony = m.invoke(tm);
Method m2 = iTelephony.getClass().getDeclaredMethod("endCall");
m2.invoke(iTelephony);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}.start();
}
}
So i have a registration Android app that in main activity creates a socket connection on create opensocket(). Everything runs perfectly on the first submit, the debugger out put looks great and it sends/recieves data back from my WPF app. Now It goes to a thanks activity which onclick leads back to my mainactivity. Now when i hit submit, it works fine, but is showing its hitting my socket methods twice (only inserts the records once on my WPF app) , and so on as many times i submit. I realize i'm not closing or reusing my socket connection correctly?! I've tried several things, but can't seem to get this to either reuse the same opensocket instance or can't just close and reopen on reload. I'm quite new to android and sockets all together, any help is greatly appreciated!
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
settingsCheck();
openSocket();
sett.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
launchSettings();
}
});
mainLogo.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
RefreshMain();
}
});
btn_register.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
tv_errors.setText("");
errorMsg = "";
nameCheck(et_lName.getText().toString(),et_fName.getText().toString());
emailCheck(et_email.getText().toString());
partnerCheck();
mobileCheck(et_mobile.getText().toString());
if (SocketHandler.SocketConnected){
if(errorMsg == ""){
//tv_errors.setText("");
if(checkForSD() == true){
sendRegistrantInfo(et_fName.getText() + "," + et_lName.getText() + "," + et_email.getText() + "," + et_mobile.getText() + "," + et_partEmail.getText() + "," + cb_terms1.isChecked() + "," + cb_terms2.isChecked() );
}
else{
tv_errors.setText("**Please insert an SD Card.");
}
}
else{
//tv_errors.setText(errorMsg);
}
}
else
{
connectionStatus.setText("Connection Error.");
tv_errors.setText("**Connection lost, please try again.");
//openSocket();
}
}
});
}
public void RefreshMain()
{
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
}
public void launchLogin()
{
Intent intent = new Intent(this, LoginActivity.class);
startActivity(intent);
}//end launchLogin
public void launchSettings()
{
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
}//end launchSettings
public void settingsCheck()
{
SharedPreferences settings = getSharedPreferences("prefs",MODE_PRIVATE);
String currentIP = settings.getString("IPSetting", "");
String currentPort = settings.getString("PORTSetting", "");
currentMem = settings.getString("SDSize", "");
if (currentIP == "" || currentPort == ""){
Intent myIntent = new Intent(this,SettingsActivity.class);
startActivity(myIntent);
}
}//end settingsCheck()
public void launchRingDialog(String id) {
final String idYo = id;
final ProgressDialog ringProgressDialog = ProgressDialog.show(MainActivity.this, "Formatting SD Card","Formatting SD Card, please wait this could take several minutes...", true);
new Thread(new Runnable() {
#Override
public void run() {
try {
fileToSD(idYo);
Thread.sleep(10000);
} catch (Exception e) {
}
ringProgressDialog.dismiss();
}
}).start();
}
public boolean checkForSD()
{
String root = "/storage/removable/sdcard1/";
double memInGigs = round(sizeMatters(root),2);
if(memInGigs >0){
return true;
}
else
{
return false;
}
}
private double sizeMatters(String path)
{
StatFs stat = new StatFs(path);
double availSize = (double)stat.getAvailableBlocks() * (double)stat.getBlockSize();
double ingigs = availSize/ 1073741824;
return ingigs;
}//end sizeMatters()
private void sendRegistrantInfo(String reg){
_sh.sendMessage(reg);
}
private void openSocket(){
_sh = new SocketHandler();
_sh.setSocketHandlerListener(this);
SharedPreferences settings = getSharedPreferences("prefs",MODE_PRIVATE);
String currentIP = settings.getString("IPSetting", "");
String currentPort = settings.getString("PORTSetting", "");
_sh.open(currentIP, currentPort);
}
#Override
protected void onPause() {
super.onPause();
}
#Override
protected void onResume() {
super.onResume();
}
#Override
public void onSocketConnected() {
Log.v(TAG, "onSocketConnected");
connectionStatus.setText("CONNECTED");
}
#Override
public void onSocketData(String msg) {
Log.v(TAG, "onSocketData - " + msg );
int usrID = Integer.parseInt(msg.trim());
if (msg != null & usrID > 0){
launchRingDialog(msg);
Intent intent = new Intent(this, ThanksActivity.class);
startActivity(intent);
}
else if(msg.trim().equals("-2") == true)
{
tv_errors.setText("**This email has already been registered for this event, please click Already Registered button to sign in.");
}
else{
tv_errors.setText("**Error, Please try submitting again.");
errorMsg = "-1";
}
}
#Override
public void onSocketDisconnected() {
Log.v(TAG, "onSocketDisconnected");
connectionStatus.setText("DISCONNECTED");
}
public class SocketHandler {
Socket sc;
public static boolean SocketConnected = false;
private static ClientThread cThread;
public String prefsFile = "prefs";
public String port = "8888";
public String ip = "192.168.1.4";
private String TAG = "SocketHandler";
protected SocketHandlerListener socketHandlerListener;
public interface SocketHandlerListener{
public void onSocketConnected();
public void onSocketData(String msg);
public void onSocketDisconnected();
}
public SocketHandler(){
}
public void setSocketHandlerListener(SocketHandlerListener shl){
socketHandlerListener = shl;
}
public void open(String ip, String port){
this.ip = ip;
this.port = port;
cThread = new ClientThread();
try{
cThread.start();
}catch (Exception ex){
Log.v(TAG, "Error connecting to socket");
}
}
public void close(){
if (cThread != null){
if (cThread.socket != null){
try {
cThread.socket.close();
} catch (Exception e) {
Log.v(TAG, "Error closing socket");
}
cThread.socket = null;
}
}
}
public void sendMessage(String msg){
cThread.sendMessage(msg);
}
public void messageRecieved(String msg){
dispatchSocketData(msg);
}
private void dispatchSocketConnected(){
if (socketHandlerListener != null){
socketHandlerListener.onSocketConnected();
}
}
private void dispatchSocketDisconnected(){
if (socketHandlerListener != null){
socketHandlerListener.onSocketDisconnected();
}
}
private void dispatchSocketData(String msg){
if (socketHandlerListener != null){
socketHandlerListener.onSocketData(msg);
}
}
public class ClientThread extends Thread {
public Socket socket;
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(ip);
Log.v(TAG, "C: Connecting..." + ip + ":" + port);
socket = new Socket(serverAddr, Integer.parseInt(port));
socket.setSoTimeout(0);
socket.setKeepAlive(true);
SocketConnected = true;
handler.post(new Runnable() {
#Override
public void run() {
dispatchSocketConnected();
}
});
// BLOCKING THE THREAD
while (SocketConnected) {
InputStream in = socket.getInputStream();
byte[] buffer = new byte[4096];
int line = in.read(buffer, 0, 4096);
while (line != -1) {
byte[] tempdata = new byte[line];
System.arraycopy(buffer, 0, tempdata, 0, line);
final String data = new String(tempdata);
handler.post(new Runnable() {
#Override
public void run() {
messageRecieved(data);
SocketConnected = false;
}
});
line = in.read(buffer, 0, 4096);
}
// break;
}
socket.close();
Log.v("Socket", "C: Closed.");
handler.post(new Runnable() {
#Override
public void run() {
dispatchSocketDisconnected();
}
});
SocketConnected = false;
} catch (Exception e) {
Log.v("Socket", "C: Error", e);
handler.post(new Runnable() {
#Override
public void run() {
dispatchSocketDisconnected();
}
});
SocketConnected = false;
}
}
Handler handler = new Handler();
public void sendMessage(String msg){
if (socket != null){
if (socket.isConnected()){
PrintWriter out;
try {
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), false);
out.print(msg);
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}
I, will be asking how to combine/fuse 2 java files if,the outstring was initiated in the BluetoothcommandService.java file I will be editing my Post sir and post my MainActivity.java file and BluetoothCommandService.java file..I just doent know how to combine it..
this is the MainActivity.java
public class MainActivity extends Activity {
//public class MainActivity extends Activity implements OnClickListener {
BluetoothAdapter BTAdapter;
BluetoothDevice BTDevice;
private TextView title;
private static final int REQUEST_DEVICE_CONNECT = 1;
private static final int REQUEST_ENABLE_BLUETOOTH = 2;
private BluetoothCommandService commandService = null;
private String connectedDeviceName = null;
//Message types sent from the Handler
public static final int MESSAGE_STATE_CHANGE = 1;
public static final int MESSAGE_READ = 2;
public static final int MESSAGE_WRITE = 3;
public static final int MESSAGE_DEVICE_NAME = 4;
public static final int MESSAGE_TOAST = 5;
public static final int RECIEVE_MESSAGE = 6;
//Will be used in BluetoothCommandSrvice jave file
public static final String TOAST = "toast";
public static final String DEVICENAME = "device name";
//#######for the controller
public static final String tagStateCTRL = "Controller";
private OutputStream outStream = null;
private static final UUID myUUID = UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
private static String address = "00:00:00:00:00:00"; // Insert your bluetooth devices MAC address
private StringBuilder sb = new StringBuilder();
Button btn_d1_on, btn_d1_off;
//for changing the device_1 name
TextView device1;
Button change;
EditText renameDevice;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main); gi move sa ubos sa request window
// Set up the window layout
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
setContentView(R.layout.activity_main);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title);
title = (TextView) findViewById(R.id.title_left_text); // Set up the custom title
title.setText(R.string.app_name); // Set up the custom title
title = (TextView) findViewById(R.id.title_right_text); // Set up the custom title
//Button openButton = (Button)findViewById(R.id.open);
//##########for the controller
btn_d1_on = (Button) findViewById(R.id.device1_on);
btn_d1_off = (Button) findViewById(R.id.device1_off);
//########for changing the device_1 name
device1 = (TextView)findViewById(R.id.device1);
change = (Button)findViewById(R.id.buttonTest);
renameDevice = (EditText)findViewById(R.id.editTest);
change.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
String change_device1 = renameDevice.getText().toString();
device1.setText(change_device1);
}
});
// AUTO REQUEST OF ENABLING THE BLUETOOTH
BTAdapter = BluetoothAdapter.getDefaultAdapter();
//A code that will detect if BT is enabled otherwise will require it.
if (BTAdapter == null)
{
//Toast.makeText(context, text, duration)
Toast.makeText(this, "No Bluetooth adapter is available.", Toast.LENGTH_LONG).show();
finish();
return;
}
//##########for the controller
btn_d1_on.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
//sendData("1");
//Toast msg = Toast.makeText(getBaseContext(), "The device is now On", Toast.LENGTH_SHORT);
//msg.show()
btn_d1_on.setEnabled(false);
sendData("1");
}
});
//##########for the controller
btn_d1_off.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
//sendData("0");
//Toast msg = Toast.makeText(getBaseContext(), "The device is now On", Toast.LENGTH_SHORT);
//msg.show();
btn_d1_off.setEnabled(false);
sendData("0");
}
});
}
#Override
protected void onStart() {
super.onStart();
//Requesting Bluetooth automatically when its not yet enabled.
if (!BTAdapter.isEnabled())
{
Intent enableIntent = new Intent (BluetoothAdapter.ACTION_REQUEST_ENABLE);
//startActivityForResult(enableIntent, 0);
startActivityForResult(enableIntent, REQUEST_ENABLE_BLUETOOTH);
}
else
{
if (commandService == null)
setupCommand();
}
}
//if (BTAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE)
//{
//Intent discoverableIntent = new Intent (BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
//discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 500);
//startActivity(discoverableIntent);
//}
#Override
protected void onResume() {
super.onResume();
if (commandService != null)
{
if (commandService.getState() == BluetoothCommandService.stateNothing)
{
commandService.start();
}
}
}
private void setupCommand()
{
commandService = new BluetoothCommandService(this, bluetoothHandler);
}
#Override
protected void onDestroy()
{
super.onDestroy();
if (commandService != null)
commandService.stop();
}
private void ensureDiscoverable()
{
//Get the current Bluetooth scan mode of the local Bluetooth adapter. The Bluetooth scan mode determines if the local adapter is connectable and/or discoverable from remote Bluetooth devices.
if (BTAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE)
{
Intent ensureDiscoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
ensureDiscoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(ensureDiscoverableIntent);
}
}
//This gets information back from the "BluetoothChatService"/"BluetoothCommandService"
//#SuppressLint("HandlerLeak")
//private final Handler bluetoothHandler = new Handler(new Handler.Callback()
#SuppressLint("HandlerLeak")
public final Handler bluetoothHandler = new Handler()
{
#Override
public void handleMessage(android.os.Message msg)
{
switch (msg.what)
{
case MESSAGE_STATE_CHANGE:
switch (msg.arg1)
{
case BluetoothCommandService.stateConnected:
title.setText(R.string.title_connectedTo);
title.append(connectedDeviceName);
break;
case BluetoothCommandService.stateConnecting:
title.setText(R.string.title_connecting);
break;
case BluetoothCommandService.stateListen:
case BluetoothCommandService.stateNothing:
title.setText(getString(R.string.title_notConnected));
break;
}
break;
case MESSAGE_DEVICE_NAME:
connectedDeviceName = msg.getData().getString(DEVICENAME);
Toast.makeText(getApplicationContext(), "Connected to " + connectedDeviceName, Toast.LENGTH_SHORT).show();
break;
case MESSAGE_TOAST:
Toast.makeText(getApplicationContext(), msg.getData().getString(TOAST), Toast.LENGTH_SHORT).show();
break;
case RECIEVE_MESSAGE: // if receive message
byte[] readBuf = (byte[]) msg.obj;
String strIncom = new String(readBuf, 0, msg.arg1); // create string from bytes array
sb.append(strIncom); // append string
int endOfLineIndex = sb.indexOf("\r\n"); // determine the end-of-line
if (endOfLineIndex > 0) { // if end-of-line,
//String sbprint = sb.substring(0, endOfLineIndex); // extract string
sb.delete(0, sb.length()); // and clear
//txtArduino.setText("Data from Arduino: " + sbprint); // update TextView
//1/4/14
btn_d1_on.setEnabled(true);
btn_d1_off.setEnabled(true);
}
//Log.d(TAG, "...String:"+ sb.toString() + "Byte:" + msg.arg1 + "...");
break;
}
//return false;
}
};
//});
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_DEVICE_CONNECT:
// When DeviceList Activity returns with a device to connect
if (resultCode == Activity.RESULT_OK) {
// Get the device MAC address
String address = data.getExtras()
.getString(DeviceList.EXTRA_DEVICE_MAC_ADDRESS);
// Get the BLuetoothDevice object
BluetoothDevice device = BTAdapter.getRemoteDevice(address);
// Attempt to connect to the device
commandService.connect(device);
}
break;
case REQUEST_ENABLE_BLUETOOTH:
// When the request to enable Bluetooth returns
if (resultCode == Activity.RESULT_OK) {
// Bluetooth is now enabled, so set up a chat session
setupCommand();
} else {
// User did not enable Bluetooth or an error occured
Toast.makeText(this, R.string.notEnabledBluetooth, Toast.LENGTH_SHORT).show();
finish();
}
}
}
#Override
//Creating an Option Menu for connectivity and discoverability of a BT device
public boolean onCreateOptionsMenu(Menu menu)
{
//MenuInflater is a class
MenuInflater OptionMenu = getMenuInflater();
//OptionMenu.inflate(menuRes, menu)
OptionMenu.inflate(R.menu.main, menu);
return true;
}
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case R.id.connect:
Intent serverIntent = new Intent(this, DeviceList.class);
//this.startActivityForResult(serverIntent, REQUEST_DEVICE_CONNECT);
startActivityForResult(serverIntent, REQUEST_DEVICE_CONNECT);
return true;
case R.id.discoverable:
ensureDiscoverable();
return true;
//case R.id.abouts:
//Intent intentabouts = new Intent(this,abouts.class);
//return true;
//default:
//return super.onOptionsItemSelected(item);
}
return false;
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if (keyCode == KeyEvent.KEYCODE_VOLUME_UP)
{
commandService.write(BluetoothCommandService.VOL_UP);
return true;
}
else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)
{
commandService.write(BluetoothCommandService.VOL_DOWN);
return true;
}
return super.onKeyDown(keyCode, event);
}
//#########################################
private void sendData(String message)
//public void sendData(String message)
{
byte[] msgBuffer = message.getBytes();
Log.d(tagStateCTRL, "...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 in the java code";
msg = msg + ".\n\nCheck that the SPP UUID: " + myUUID.toString() + " exists on server.\n\n";
errorExit("Fatal Error", msg);
}
}
private void errorExit(String title, String message){
Toast msg = Toast.makeText(getBaseContext(),
title + " - " + message, Toast.LENGTH_SHORT);
msg.show();
finish();
}
//#########################################
}
This is the BluetoothCommanService.java
public class BluetoothCommandService {
private final BluetoothAdapter BTAdapter;
private final Handler bluetoothHandler;
private int connectionState;
private ConnectThread connectThread;
//private ConnectedThread connectedThread;
public ConnectedThread connectedThread;
//***Added 12/27/13
private AcceptThread mainAcceptThread;
//connection states of the Bluetooth
public static final int stateNothing = 0; //doing nothing
public static final int stateListen = 1; //listening for incoming connections
public static final int stateConnecting = 2; //initiating an outgoing connection
public static final int stateConnected = 3;
//constants that indicate command to computer
public static final int exitCMD = -1;
public static final int VOL_UP = 1;
public static final int VOL_DOWN = 2;
private static final boolean D = true;
private static final String tagState = "BluetoothCommandService";
//universally unique identifier (UUID)
//The intent of UUIDs is to enable distributed systems to uniquely identify information without significant central coordination
//private static final UUID myUUID = UUID.fromString("04c6093b-0000-1000-8000-00805f9b34fb");
private static final UUID myUUID = UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
//Name for the SDP (don;t know what is it) record when creating server socket
private static final String name = "BluetoothCommand";
public BluetoothCommandService(Context context, Handler handler) { // context == UI Activity Context && handler == send message back to the UI Activity
BTAdapter = BluetoothAdapter.getDefaultAdapter();
connectionState = stateNothing;
bluetoothHandler = handler;
}
private synchronized void setState(int state) { // state == current connection state; an integer
if (D) Log.d(tagState, "setState() " + connectionState + " -> " + state);
connectionState = state;
//Give the new state to the Handler so that the UI Activity can update
//bluetoothHandler.obtainMessage(what, arg1, arg2)
bluetoothHandler.obtainMessage(MainActivity.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
}
public synchronized int getState() { //return the current connection state
return connectionState;
}
public synchronized void start() {
if (D) Log.d(tagState, "start");
// Cancel any thread attempting to make a connection
if (connectThread != null)
{
connectThread.cancel();
connectThread = null;
}
// Cancel any thread currently running a connection
if (connectedThread != null)
{
connectedThread.cancel();
connectedThread = null;
}
// Start the thread to listen on a BluetoothServerSocket
if (mainAcceptThread == null)
{
mainAcceptThread = new AcceptThread();
mainAcceptThread.start();
}
setState(stateListen);
}
//device == the BluetoothDevice to connect
public synchronized void connect(BluetoothDevice device) {
if (D) Log.d(tagState, "connect to: " + device);
// Cancel any thread attempting to make a connection
if (connectionState == stateConnecting) {
if (connectThread != null)
{
connectThread.cancel();
connectThread = null;
}
}
// Cancel any thread currently running a connection
if (connectedThread != null)
{
connectedThread.cancel();
connectedThread = null;
}
// Cancel the accept thread because we only want to connect to one device
if (mainAcceptThread != null)
{
mainAcceptThread.cancel();
mainAcceptThread = null;
}
// Start the thread to connect with the given device
connectThread = new ConnectThread(device);
connectThread.start();
setState(stateConnecting);
}
public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) {
if (D) Log.d(tagState, "connected");
// Cancel the thread that completed the connection
if (connectThread != null)
{
connectThread.cancel();
connectThread = null;
}
// Cancel any thread currently running a connection
if (connectedThread != null)
{
connectedThread.cancel();
connectedThread = null;
}
if (mainAcceptThread != null)
{
mainAcceptThread.cancel();
mainAcceptThread = null;
}
// Start the thread to manage the connection and perform transmissions
connectedThread = new ConnectedThread(socket);
connectedThread.start();
Message msg = bluetoothHandler.obtainMessage(MainActivity.MESSAGE_DEVICE_NAME);
Bundle bundle = new Bundle();
bundle.putString(MainActivity.DEVICENAME, device.getName());
msg.setData(bundle);
bluetoothHandler.sendMessage(msg);
setState(stateConnected);
}
public synchronized void stop() {
if (D) Log.d(tagState, "stop");
if (connectThread != null)
{
connectThread.cancel();
connectThread = null;
}
if (connectedThread != null)
{
connectedThread.cancel();
connectedThread = null;
}
if (mainAcceptThread != null)
{
mainAcceptThread.cancel();
mainAcceptThread = null;
}
setState(stateNothing);
}
public void write(byte[] out) {
ConnectedThread r;
synchronized (this) {
if (connectionState != stateConnected) return;
r = connectedThread;
}
r.write(out);
}
public void write(int out) {
// Create temporary object
ConnectedThread r;
// Synchronize a copy of the ConnectedThread
synchronized (this) {
if (connectionState != stateConnected) return;
r = connectedThread;
}
// Perform the write unsynchronized
r.write(out);
}
private void connectionFailed() {
setState(stateListen);
// Send a failure message back to the Activity
Message msg = bluetoothHandler.obtainMessage(MainActivity.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(MainActivity.TOAST, "Unable to connect device");
msg.setData(bundle);
bluetoothHandler.sendMessage(msg);
}
/**
* Indicate that the connection was lost and notify the UI Activity.
*/
private void connectionLost() {
setState(stateListen);
Message msg = bluetoothHandler.obtainMessage(MainActivity.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(MainActivity.TOAST, "Device connection was lost");
msg.setData(bundle);
bluetoothHandler.sendMessage(msg);
}
private class ConnectThread extends Thread {
private final BluetoothSocket connectThread_socket;
private final BluetoothDevice connectThread_device;
public ConnectThread(BluetoothDevice device) {
connectThread_device = device;
BluetoothSocket tmp = null;
//Get a BluetoothSocket for a connection w/ the given BT device
//try {
//catch (IOException e) {
//Log.e(tag, msg, tr)
//Log.e(tagState, "create() failed", e);}
//Added 12/28/13
Method m;
try {
m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
tmp = (BluetoothSocket) m.invoke(device, 1);
} catch (SecurityException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (NoSuchMethodException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
connectThread_socket = tmp;
}
public void run() {
Log.i(tagState, "BEGIN ConnectThread");
setName("ConnectThread");
BTAdapter.cancelDiscovery();
// Make a connection to the BluetoothSocket
try {
connectThread_socket.connect();}
catch (IOException e) {
connectionFailed();
try {
connectThread_socket.close();
} catch (IOException e2) {
Log.e(tagState, "Unable to close() socket during connection failure", e2);
}
BluetoothCommandService.this.start();
return;
}
// Reset the ConnectThread because we're done
synchronized (BluetoothCommandService.this) {
connectThread = null;
}
// Start the connected thread
connected(connectThread_socket, connectThread_device); //ERROR: will still create "connected"
}
public void cancel() {
try {
connectThread_socket.close();
} catch (IOException e) {
Log.e(tagState, "close() of connect socket failed", e);
}
}
}
private class ConnectedThread extends Thread {
private final BluetoothSocket connectedThread_socket;
private final InputStream connectedThread_inStream;
private final OutputStream connectedThread_outStream;
public ConnectedThread(BluetoothSocket socket) {
Log.d(tagState, "create ConnectedThread");
connectedThread_socket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the BluetoothSocket input and output streams
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
Log.e(tagState, "temp sockets not created", e);
}
connectedThread_inStream = tmpIn;
connectedThread_outStream = tmpOut;
}
public void run() {
Log.i(tagState, "BEGIN ConnectedThread");
byte[] buffer = new byte[1024]; // WALA JUD KO KASABOT ANI MAN :D
while (true) {
try {
int bytes = connectedThread_inStream.read(buffer);
bluetoothHandler.obtainMessage(MainActivity.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e(tagState, "disconnected", e);
connectionLost(); //ERROR: will still create "private void CONNECTIONLOST"
break;
}
}
}
public void write(byte[] buffer) {
try {
connectedThread_outStream.write(buffer);
} catch (IOException e) {
Log.e(tagState, "Exception during write", e);
}
}
public void write(int out) {
try {
connectedThread_outStream.write(out);
} catch (IOException e) {
Log.e(tagState, "Exception during write", e);
}
}
public void cancel() {
try {
connectedThread_outStream.write(exitCMD);
connectedThread_socket.close();
} catch (IOException e) {
Log.e(tagState, "close() of connect socket failed", e);
}
}
}
private class AcceptThread extends Thread {
// The local server socket
private final BluetoothServerSocket acceptThread_ServerSocket;
public AcceptThread() {
BluetoothServerSocket tmp = null;
// Create a new listening server socket
try {
tmp = BTAdapter.listenUsingRfcommWithServiceRecord(name, myUUID);
} catch (IOException e) {
Log.e(tagState, "listen() failed", e);
}
acceptThread_ServerSocket = tmp;
}
public void run() {
if (D) Log.d(tagState, "BEGIN mainAcceptThread" + this);
setName("AcceptThread");
BluetoothSocket socket = null;
while (connectionState != stateConnected) {
try {
socket = acceptThread_ServerSocket.accept();
} catch (IOException e) {
Log.e(tagState, "accept() failed", e);
break;
}
if (socket != null) {
synchronized (BluetoothCommandService.this) {
switch (connectionState) {
case stateListen:
case stateConnecting:
connected(socket, socket.getRemoteDevice());
break;
case stateNothing:
case stateConnected:
try {
socket.close();
} catch (IOException e) {
Log.e(tagState, "Could not close unwanted socket", e);
}
break;
}
}
}
}
if (D) Log.i(tagState, "END mainAcceptThread");
}
public void cancel() {
if (D) Log.d(tagState, "cancel " + this);
try {
acceptThread_ServerSocket.close();
} catch (IOException e) {
Log.e(tagState, "close() of server failed", e);
}
}
}
}