Related
I'm stuck and can't find a way to restart or reconnect the Bluetooth service in my app. The app has 3 fragments, tabs managed by FragmentPagerAdapter.
In the first fragment you can discover, associate and communicate with the BT device. In the second and third card it is necessary to interact with the device, it is not possible to get the connection or keep the service connected.
Here it goes the first fragment:
public class Conexiones extends Fragment implements ServiceConnection, SerialListener {
public BluetoothAdapter BTAdapter;
private ListView listView; // detectados
private ArrayList<String> mDeviceList;
public Button conectar, actualizar;
private ArrayAdapter m_DiscoveredPeersAdapter;
BluetoothDevice bdDevice;
BluetoothClass dbClass;
ArrayList<BluetoothDevice> listaBTDevices = null;
View view;
public SerialSocket socket;
public SerialService service;
public Conexiones(){
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
view = inflater.inflate(R.layout.fragment_conexiones, container, false );
BTAdapter = BluetoothAdapter.getDefaultAdapter();
listView = (ListView) this.view.findViewById(R.id.listView);
mDeviceList = new ArrayList<>();
m_DiscoveredPeersAdapter = new ArrayAdapter(getActivity(), android.R.layout.simple_list_item_1, mDeviceList);
listView.setAdapter(m_DiscoveredPeersAdapter);
listItemClicked = new ListItemClicked();
clicked = new ButtonClicked();
checkBTPermissions();
listaBTDevices = new ArrayList<BluetoothDevice>();
m_DiscoveredPeersAdapter.notifyDataSetChanged();
if (BTAdapter == null || !BTAdapter.isEnabled()) {
Intent turnOn = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(turnOn, 1);
}
int MY_PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION = 1;
ActivityCompat.requestPermissions(activity,
new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
MY_PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION);
if (BTAdapter.isEnabled()){
BTAdapter.startDiscovery();
Log.e("mio", "dp de star discovery");
}
else{
Intent turnOn = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(turnOn, 1);
Log.e("mio", "no weisa");
}
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
activity.registerReceiver(mReceiver, filter);
return view;
}
#Override
public void onStart() {
Log.e("mio", "dentro de on start ");
dataInicialRecibida=false;
super.onStart();
//getPairedDevices();
this.conectar.setOnClickListener(clicked);
this.actualizar.setOnClickListener(clicked);
listView.setOnItemClickListener(listItemClicked);
MainActivity activity = (MainActivity) getActivity();
texto.setText("sistema listo");
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.i("BT", "recibe");
if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
//discovery starts, we can show progress dialog or perform other tasks
Log.i("BT", "empezamos BT");
}
if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
//discovery starts, we can show progress dialog or perform other tasks
Log.i("BT", "terminiamos BT");
try {
Method getUuidsMethod = BluetoothAdapter.class.getDeclaredMethod("getUuids", null);
ParcelUuid[] uuids = (ParcelUuid[]) getUuidsMethod.invoke(BTAdapter, null);
if(uuids != null) {
for (ParcelUuid uuid : uuids) {
Log.d(TAG, "UUID: " + uuid.getUuid().toString());
miu=uuid.getUuid().toString();
}
}else{
Log.d(TAG, "Uuids not found, be sure to enable Bluetooth!");
}
}catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
//discovery starts, we can show progress dialog or perform other tasks
Log.i("BT", "state changed BT");
}
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// mDeviceList.add(device.getName() + "\n" + device.getAddress());
// DeviceItem newDevice = new DeviceItem(device.getName(), device.getAddress(), "false");
Log.i("BTN", device.getName() + "\n" + device.getAddress());
// mDeviceList.notifyDataSetChanged();
if(listaBTDevices.size()<1) // this checks if the size of bluetooth device is 0,then add the
{
Log.i("mio", "lista devices menor a 1");// device to the arraylist.
m_DiscoveredPeersAdapter.add(device.getName()+"\n"+device.getAddress());
listaBTDevices.add(device);
m_DiscoveredPeersAdapter.notifyDataSetChanged();
}
else
{
Log.i("mio", "lista devices maor o igual a 1");
boolean flag = true; // flag to indicate that particular device is already in the arlist or not
for(int i = 0; i<listaBTDevices.size();i++)
{
if(device.getAddress().equals(listaBTDevices.get(i).getAddress()))
{
flag = false;
}
}
if(flag == true)
{
m_DiscoveredPeersAdapter.add(device.getName()+"\n"+device.getAddress());
listaBTDevices.add(device);
m_DiscoveredPeersAdapter.notifyDataSetChanged();
}
}
}
listView.setAdapter(new ArrayAdapter<String>(context,
android.R.layout.simple_list_item_1, mDeviceList));
}
};
#RequiresApi(api = Build.VERSION_CODES.M)
private void checkBTPermissions() {
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP){
int permissionCheck =getActivity().checkSelfPermission("Manifest.permission.ACCESS_FINE_LOCATION");
permissionCheck += getActivity().checkSelfPermission("Manifest.permission.ACCESS_COARSE_LOCATION");
if (permissionCheck != 0) {
this.requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, 1001); //Any number
}
}else{
Log.d(TAG, "checkBTPermissions: No need to check permissions. SDK version < LOLLIPOP.");
}
}
#Override
public void onDestroy() {
MainActivity activity = (MainActivity) getActivity();
activity.unregisterReceiver(mReceiver);
super.onDestroy();
Log.e("mio", "on destroy ");
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == RESULT_OK){
Log.d(TAG, "caso okookok.");
BTAdapter.startDiscovery();
}else{
Log.d(TAG, "cas no ok.");
}
}
#Override
public void onStop() {
super.onStop();
Log.e("mio", "on stop");
MainActivity activity = (MainActivity) getActivity();
activity.unregisterReceiver(mReceiver);
}
#Override
public void onServiceConnected(ComponentName name, IBinder binder) {
service = ((SerialService.SerialBinder) binder).getService();
Log.e("mio", "on service conectado conexiones ");
if(initialStart && isResumed()) {
initialStart = false;
getActivity().runOnUiThread(this::connect);
}
}
#Override
public void onServiceDisconnected(ComponentName name) {
service = null;
texto.setText("desconectado BT");
Log.e("mio", "desconectado BT conexiones");
}
#Override
public void onSerialConnect() {
texto.setText("conexion BT");
Log.e("mio", "conectado BT conexiones");
}
#Override
public void onSerialConnectError(Exception e) {
texto.setText("error conexion BT");
Log.e("mio", "onSerialConnectError");
}
#Override
public void onSerialRead(byte[] data) {
receive(data);
texto.setText("leyendo BT");
Log.e("mio", "leyendo BT ");
}
private void receive(byte[] data) {
receiveText+=new String(data);
receiveText="";
}
#Override
public void onSerialIoError(Exception e) {
texto.setText("error conexion BT");
}
class ButtonClicked implements View.OnClickListener
{
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.button:
listaBTDevices.clear();
m_DiscoveredPeersAdapter.clear();
startSearching();
texto.setText("buscando dispositivos BT");
break;
case R.id.button3:
break;
}
}
}
class ListItemClicked implements AdapterView.OnItemClickListener
{
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
bdDevice = listaBTDevices.get(position);
//bdClass = arrayListBluetoothDevices.get(position);
Log.i("Log", "The dvice : "+bdDevice.toString());
connect();
}
}
private boolean isNetworkAvailable() {
ConnectivityManager connectivityManager = (ConnectivityManager) service.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
private void getPairedDevices() {
// Set<BluetoothDevice> pairedDevice = BTAdapter.getBondedDevices();
// if(pairedDevice.size()>0)
{
// for(BluetoothDevice device : pairedDevice)
{
// arrayListpaired.add(device.getName()+"\n"+device.getAddress());
// arrayListPairedBluetoothDevices.add(device);
}
}
// adapter.notifyDataSetChanged();
}
public void send(String str) {
try {
SpannableStringBuilder spn = new SpannableStringBuilder(str+'\n');
byte[] data = (str).getBytes();
socket.write(data);
} catch (Exception e) {
onSerialIoError(e);
}
}
#SuppressWarnings("deprecation")
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// getActivity().bindService(new Intent(getActivity(), SerialService.class), this, Context.BIND_AUTO_CREATE);
}
private void connect() {
try {
BTAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothDevice device = BTAdapter .getRemoteDevice(bdDevice.getAddress());
String deviceName = device.getName() != null ? device.getName() : device.getAddress();
socket = new SerialSocket();
service.connect(this, "Connected to " + deviceName);
socket.connect(getContext(), service, device);
MainActivity activity = (MainActivity) getActivity();
activity.setidEquipo(bdDevice.getAddress());
// conexión ok, cambiar color letras boton
} catch (Exception e) {
//onSerialConnectError(e);
Log.i("mio", "error del connect "+e);
// sino hay conexión mantener boton con letras naranjas
}
}
private void startSearching() {
Log.i("Log", "in the start searching method");
MainActivity activity = (MainActivity) getActivity();
IntentFilter intentFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
activity.registerReceiver(mReceiver, intentFilter);
BTAdapter.startDiscovery();
}
private void onBluetooth() {
if(!BTAdapter.isEnabled())
{
BTAdapter.enable();
Log.i("Log", "Bluetooth is Enabled");
}
}
private void offBluetooth() {
if(BTAdapter.isEnabled())
{
BTAdapter.disable();
}
}
}
The serial service:
public class SerialService extends Service implements SerialListener {
class SerialBinder extends Binder {
SerialService getService() { return SerialService.this; }
}
private enum QueueType {Connect, ConnectError, Read, IoError}
private class QueueItem {
QueueType type;
byte[] data;
Exception e;
QueueItem(QueueType type, byte[] data, Exception e) { this.type=type; this.data=data; this.e=e; }
}
private final Handler mainLooper;
private final IBinder binder;
private final Queue<QueueItem> queue1, queue2;
private SerialListener listener;
private boolean connected;
private String notificationMsg;
public SerialService() {
mainLooper = new Handler(Looper.getMainLooper());
binder = new SerialBinder();
queue1 = new LinkedList<>();
queue2 = new LinkedList<>();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return binder;
}
public void connect(SerialListener listener, String notificationMsg) {
this.listener = listener;
connected = true;
this.notificationMsg = notificationMsg;
}
public void disconnect() {
listener = null;
connected = false;
notificationMsg = null;
}
public void attach(SerialListener listener) {
if(Looper.getMainLooper().getThread() != Thread.currentThread())
throw new IllegalArgumentException("not in main thread");
cancelNotification();
// use synchronized() to prevent new items in queue2
// new items will not be added to queue1 because mainLooper.post and attach() run in main thread
if(connected) {
synchronized (this) {
this.listener = listener;
}
}
for(QueueItem item : queue1) {
switch(item.type) {
case Connect: listener.onSerialConnect (); break;
case ConnectError: listener.onSerialConnectError (item.e); break;
case Read: listener.onSerialRead (item.data); break;
case IoError: listener.onSerialIoError (item.e); break;
}
}
for(QueueItem item : queue2) {
switch(item.type) {
case Connect: listener.onSerialConnect (); break;
case ConnectError: listener.onSerialConnectError (item.e); break;
case Read: listener.onSerialRead (item.data); break;
case IoError: listener.onSerialIoError (item.e); break;
}
}
queue1.clear();
queue2.clear();
}
public void detach() {
if(connected)
createNotification();
// items already in event queue (posted before detach() to mainLooper) will end up in queue1
// items occurring later, will be moved directly to queue2
// detach() and mainLooper.post run in the main thread, so all items are caught
listener = null;
}
public void onSerialConnect() {
Log.i("mio", "dentro on serial connect ");
if(connected) {
Log.i("mio", "dentro de connected ");
synchronized (this) {
if (listener != null) {
mainLooper.post(() -> {
if (listener != null) {
listener.onSerialConnect();
} else {
queue1.add(new QueueItem(QueueType.Connect, null, null));
}
});
} else {
queue2.add(new QueueItem(QueueType.Connect, null, null));
}
}
}
}
public void onSerialConnectError(Exception e) {
if(connected) {
synchronized (this) {
if (listener != null) {
mainLooper.post(() -> {
if (listener != null) {
listener.onSerialConnectError(e);
} else {
queue1.add(new QueueItem(QueueType.ConnectError, null, e));
cancelNotification();
disconnect();
}
});
} else {
queue2.add(new QueueItem(QueueType.ConnectError, null, e));
cancelNotification();
disconnect();
}
}
}
}
public void onSerialRead(byte[] data) {
if(connected) {
synchronized (this) {
if (listener != null) {
mainLooper.post(() -> {
if (listener != null) {
listener.onSerialRead(data);
} else {
queue1.add(new QueueItem(QueueType.Read, data, null));
}
});
} else {
queue2.add(new QueueItem(QueueType.Read, data, null));
}
}
}
}
public void onSerialIoError(Exception e) {
if(connected) {
synchronized (this) {
if (listener != null) {
mainLooper.post(() -> {
if (listener != null) {
listener.onSerialIoError(e);
} else {
queue1.add(new QueueItem(QueueType.IoError, null, e));
cancelNotification();
disconnect();
}
});
} else {
queue2.add(new QueueItem(QueueType.IoError, null, e));
cancelNotification();
disconnect();
}
}
}
}
}
The serial socket class:
class SerialSocket implements Runnable {
private static final UUID BLUETOOTH_SPP = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
private final BroadcastReceiver disconnectBroadcastReceiver;
private Context context;
private SerialListener listener;
private BluetoothDevice device;
private BluetoothSocket socket;
private boolean connected;
SerialSocket() {
disconnectBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(listener != null)
listener.onSerialIoError(new IOException("background disconnect"));
disconnect(); // disconnect now, else would be queued until UI re-attached
}
};
}
/**
* connect-success and most connect-errors are returned asynchronously to listener
*/
void connect(Context context, SerialListener listener, BluetoothDevice device) throws IOException {
if(connected || socket != null)
throw new IOException("already connected");
this.context = context;
this.listener = listener;
this.device = device;
context.registerReceiver(disconnectBroadcastReceiver, new IntentFilter(Constants.INTENT_ACTION_DISCONNECT));
Executors.newSingleThreadExecutor().submit(this);
}
void disconnect() {
listener = null; // ignore remaining data and errors
// connected = false; // run loop will reset connected
if(socket != null) {
try {
socket.close();
} catch (Exception ignored) {
}
socket = null;
}
try {
context.unregisterReceiver(disconnectBroadcastReceiver);
} catch (Exception ignored) {
}
}
void write(byte[] data) throws IOException {
if (!connected)
throw new IOException("not connected");
socket.getOutputStream().write(data);
}
#Override
public void run() { // connect & read
try {
socket = device.createRfcommSocketToServiceRecord(BLUETOOTH_SPP);
socket.connect();
if(listener != null)
listener.onSerialConnect();
} catch (Exception e) {
if(listener != null)
listener.onSerialConnectError(e);
try {
socket.close();
} catch (Exception ignored) {
}
socket = null;
return;
}
connected = true;
try {
byte[] buffer = new byte[1024];
int len;
//noinspection InfiniteLoopStatement
while (true) {
len = socket.getInputStream().read(buffer);
byte[] data = Arrays.copyOf(buffer, len);
if(listener != null)
listener.onSerialRead(data);
}
} catch (Exception e) {
connected = false;
if (listener != null)
listener.onSerialIoError(e);
try {
socket.close();
} catch (Exception ignored) {
}
socket = null;
}
}
}
And the second fragment whereas I need to keep connection or connect to the same device already connected in fragment ("conexiones"):
public class Identificacion extends Fragment implements ServiceConnection, SerialListener {
private String deviceAddress;
private String newline = "\r\n";
private String receiveText;
private enum Connected { False, Pending, True }
private String sendText;
private SerialSocket socket;
private SerialService service;
private boolean initialStart = true;
private Connected connected = Connected.False;
// constructor requerido vacio
public Identificacion(){
}
#Override
public void onCreate(Bundle savedInstanceState) {
Log.e("mio", "dentro on creata identificacion");
super.onCreate(savedInstanceState);
setRetainInstance(true);
// deviceAddress = getArguments().getString("device");
}
#SuppressWarnings("deprecation") // onAttach(context) was added with API 23. onAttach(activity) works for all API versions
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
getActivity().bindService(new Intent(getActivity(), SerialService.class), this, Context.BIND_AUTO_CREATE);
}
#Override
public void onDetach() {
try { getActivity().unbindService(this); } catch(Exception ignored) {}
super.onDetach();
}
#Override
public void onResume() {
super.onResume();
/* if(initialStart && service !=null) {
initialStart = false;
getActivity().runOnUiThread(this::connect);
} */
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
view = inflater.inflate(R.layout.fragment_identificacion, container, false );
return view;
}
private void addListenerOnButton() {
bt12.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
EditText txtView = (EditText) aux1;
EditText txtView2 = (EditText) aux2;
TextView txtView3 = (TextView) aux3;
if (pin2 != null && pin2.length() == largo && pin4 != null && pin4.length() == largo){
//consultar BD si exta bien la pass, caso si:
Log.e("mio", "dentro de pin y pass con formato " + pin2);
pin=pin2;
String aenvio=(String)pin2+";"+pin4;
// enviar pin por BT
connect();
send(aenvio);
}
}
});
}// fin add listener button
private void connect() {
try {
MainActivity activity = (MainActivity) getActivity();
String par3= activity.getidEquipo();
deviceAddress=par3;
Log.e("mio", "connect identif valor deviceAddress "+deviceAddress);
//deviceAddress = getArguments().getString("device");
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothDevice device = bluetoothAdapter.getRemoteDevice(deviceAddress);
String deviceName = device.getName() != null ? device.getName() : device.getAddress();
// status("connecting...");
Log.e("mio", "connect identif deviceName "+deviceName);
connected = Connected.Pending;
onAttach(activity);
// socket =
//socket = new SerialSocket();
getActivity().bindService(new Intent(getActivity(), SerialService.class ), this, Context.BIND_ADJUST_WITH_ACTIVITY );
service.connect(this, "Connected to " + deviceName);
socket.connect(getContext(), service, device);
connected = Connected.True;
Log.e("mio", "connect identif salida "+deviceName);
} catch (Exception e) {
onSerialConnectError(e);
}
}
private void send(String str) {
if(connected != Connected.True) {
Toast.makeText(getActivity(), "not connected", Toast.LENGTH_SHORT).show();
Log.e("mio", "dentro send no conectado "+str);
// return;
}
try {
connect();
// SpannableStringBuilder spn = new SpannableStringBuilder(str+'\n');
Log.e("mio", "send conectado "+str);
// spn.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.colorSendText)), 0, spn.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
Toast.makeText(getActivity(), "enviando login a esp", Toast.LENGTH_SHORT).show();
sendText=str; // poner aca el string de user;pass a enviar al esp32 app
byte[] data = (str + newline).getBytes();
socket.write(data);
} catch (Exception e) {
onSerialIoError(e);
}
}
private void receive(byte[] data) {
receiveText+=(new String(data));
}
#Override
public void onServiceConnected(ComponentName name, IBinder binder) {
service = ((SerialService.SerialBinder) binder).getService();
if(initialStart && isResumed()) {
initialStart = false;
getActivity().runOnUiThread(this::connect);
}
}
#Override
public void onServiceDisconnected(ComponentName name) {
service = null;
}
#Override
public void onSerialRead(byte[] data) {
Log.e("mio", "serial leer data ");
receive(data);
}
#Override
public void onSerialIoError(Exception e) {
Log.e("mio", "serial io error, desconectar ");
disconnect();
}
}
Managing code when you are using Bluetooth or system-related task is too hard because it creates a tightly coupled code eventually turn into the buggy code. So you can use this and this libraries to do your task neat and cleanly. Please check the example app for my suggested first and second libraries. If you face any struck in implementation let me know.
Run service from an activity or from the App class.
upd:
Or use singleton as a main point to communicate with the BluetoothHelper
I solved this of my way, by keeping the bluetooth socket static.
I've setted the 'boolean' object {TRUE, PENDING, FALSE}, in service and handled this object with service listener in others activities.
in the activities i unbind the service but do not disconnect socket, but as i don't disconnect from socket when change activities, there's a memory leak, but for me isn't a problem.
result:
the socket keeps connected and i can access the device from all activities, and the error handling (discconect, bluetooth off) happens thanks to listener
Create a service running in a different process not the main app process. Communicate with main app and service using broadcast receivers. This makes sure you can be anywhere in main app but you can still interact with Ble service
solved moving all the bluetooth code: broadcast receiver, service instance and socket instance, to the main activity, then in the fragments the service is attached (bind service) or (if null) started again.
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
Log.e("mio", "dentro de is visible to user identif ");
// connect();
if(service != null){
service.attach(this);
Log.e("mio", "caso attach ");
}
else{
Log.e("mio", "caso start service 1 ");
getActivity().startService(new Intent(getActivity(), SerialService.class)); // prevents service destroy on unbind from recreated activity caused by orientation change
// service.attach(this);
}
This solves the problem nice and easy, so the service is available when user see data in the fragment, and communication is well received and sent.
So basically, i got a list view that shows a list of bands.
When i press on one of the bands in the list, it creates a band profile page via an adapter.
In this layout, i got a play button, which starts a MediaPlayer service and play a song.
So far, so good.
The problem is, im trying to update the seekBar, located in the band profile page (created by the adapter mentioned above), from the MediaPlayer service Java file, but i'm unable to reach it.
i'm trying to use :
LayoutInflater inflater = (LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.activity_singleband, null, false);
seekBar = (SeekBar) layout.findViewById(R.id.seekBarBand);
but it seems that it uses another "instance" of the view, and not the one i'm currently viewing.
Here is the full MusicService Java file:
public class MusicService extends Service {
SeekBar seekBar;
Handler handler;
Runnable runnable;
NotificationManager nMN;
TextView BandName;
String songLink;
String songName;
String bandName;
String SongPlaying="";
String BandPlaying="";
public static MediaPlayer mp;
public static Boolean mpState = true;
public static Boolean mpPause = false;
public static Boolean isPlaying = false;
#Override
public void onCreate() {
super.onCreate();
}
// Play Cycle for seekBar
public void PlayCycle(){
seekBar.setProgress(mp.getCurrentPosition());
if (mp.isPlaying()){
runnable = new Runnable() {
#Override
public void run() {
PlayCycle();
}
};
handler.postDelayed(runnable, 1000);
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
songLink = intent.getStringExtra("SongLink");
songName = intent.getStringExtra("SongName");
bandName = intent.getStringExtra("BandName");
LayoutInflater inflater = (LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.activity_singleband, null, false);
seekBar = (SeekBar) layout.findViewById(R.id.seekBarBand);
BandName = (TextView) layout.findViewById(R.id.singleBandNameView);
BandName.setText("Bla Bla");
System.out.print("Band Name : "+ BandName.getText() );
handler = new Handler();
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean input) {
if (input){
mp.seekTo(progress);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
if (isPlaying && !songName.equals(SongPlaying) && !BandPlaying.equals(bandName)) {
Stop();
mp = new MediaPlayer();
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
Uri songUri = Uri.parse(songLink);
mp.setDataSource(getApplicationContext(), songUri);
SongPlaying = songName;
Toast.makeText(getApplicationContext(), "Please wait", Toast.LENGTH_SHORT).show();
isPlaying=true;
new prepare().execute();
}
catch (IOException e) {
e.printStackTrace();
}
}
else if (!isPlaying && !songName.equals(SongPlaying) && !BandPlaying.equals(bandName) ) {
mp = new MediaPlayer();
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
Uri songUri = Uri.parse(songLink);
mp.setDataSource(getApplicationContext(), songUri);
SongPlaying = songName;
Toast.makeText(getApplicationContext(), "Please wait", Toast.LENGTH_SHORT).show();
new prepare().execute();
isPlaying=true;
}
catch (IOException e) {
e.printStackTrace();
}
}
else {
Toast.makeText(getApplicationContext(), "Song is Already Playing", Toast.LENGTH_SHORT).show();
}
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
super.onDestroy();
mp.release();
handler.removeCallbacks(runnable);
}
/// Permanent Notification
private void showNotification() {
nMN = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Notification n = new Notification.Builder(this)
.setContentTitle(songName)
.setContentText(bandName)
.setSmallIcon(R.drawable.ic_bandcamp)
//.addAction(R.drawable.ic_play_arrow_black_24dp, "button1", new pause())
.setOngoing(true)
.build();
nMN.notify(1, n);
}
/// PREPARE SONG TO PLAY //
public class prepare extends AsyncTask {
#Override
protected Object doInBackground(Object[] objects) {
try {
mp.prepare();
PlayCycle();
seekBar.setMax(mp.getDuration());
mp.start();
SongPlaying = songName;
isPlaying=true;
showNotification(); // show notification
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
Toast.makeText(getApplicationContext(),"Song Finished", Toast.LENGTH_LONG).show();
new stop().execute();
}
});
} catch (IOException io){ io.printStackTrace(); }
return null; }}
/// STOP PLAYING SONG //
public static void Stop()
{
mp.reset();
mp.release();
isPlaying=false;
}
public static class stop extends AsyncTask {
#Override
protected Object doInBackground(Object[] objects) {
try {
mp.reset();
mp.release();
isPlaying=false;
} catch (Exception io){ io.printStackTrace(); }
return null; }}
/// PAUSE PLAYING SONG//
public static class pause extends AsyncTask {
#Override
protected Object doInBackground(Object[] objects) {
try {
mp.pause(); }
catch (Exception io){ io.printStackTrace(); }
return null; }}
public static class start extends AsyncTask {
#Override
protected Object doInBackground(Object[] objects) {
try {
mp.start(); }
catch (Exception io){ io.printStackTrace(); }
return null; }}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
Would love to have some suggestions.
Thanks in advance.
Okey Firstly I suggest you to read more about Android Service classes. Secondly Do NOT place you visual components like a SeekBar or TextView in the Service because it doesn't make any sense. Service is just a background task and do not know about the UI. Since it's executed in the background you don't even need AsyncTask inside this so thirdly remove ALL AsyncTasks in your service and run their task like they don't need to be executed in the background.
So all what you have to do is create a Fragment/Activity for the UI, then bind your Fragment/Acitivity with your Service to communicate and update UI components.
The easiest way is make the Service a Singleton like it's done here:
public class MusicService extends Service {
private static MusicService instance = null;
public static MusicService getInstance() {
return instance;
}
Handler handler;
Runnable runnable;
NotificationManager nMN;
String songLink;
String songName;
String bandName;
String SongPlaying="";
String BandPlaying="";
public static MediaPlayer mp;
public static Boolean mpState = true;
public static Boolean mpPause = false;
public static Boolean isPlaying = false;
#Override
public void onCreate() {
instance = this;
super.onCreate();
}
// Play Cycle for seekBar
public void PlayCycle(){
seekBar.setProgress(mp.getCurrentPosition());
if (mp.isPlaying()){
runnable = new Runnable() {
#Override
public void run() {
PlayCycle();
}
};
handler.postDelayed(runnable, 1000);
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
songLink = intent.getStringExtra("SongLink");
songName = intent.getStringExtra("SongName");
bandName = intent.getStringExtra("BandName");
handler = new Handler();
if (isPlaying && !songName.equals(SongPlaying) && !BandPlaying.equals(bandName)) {
Stop();
mp = new MediaPlayer();
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
Uri songUri = Uri.parse(songLink);
mp.setDataSource(getApplicationContext(), songUri);
SongPlaying = songName;
Toast.makeText(getApplicationContext(), "Please wait", Toast.LENGTH_SHORT).show();
isPlaying=true;
new prepare().execute();
}
catch (IOException e) {
e.printStackTrace();
}
}
else if (!isPlaying && !songName.equals(SongPlaying) && !BandPlaying.equals(bandName) ) {
mp = new MediaPlayer();
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
Uri songUri = Uri.parse(songLink);
mp.setDataSource(getApplicationContext(), songUri);
SongPlaying = songName;
Toast.makeText(getApplicationContext(), "Please wait", Toast.LENGTH_SHORT).show();
new prepare().execute();
isPlaying=true;
}
catch (IOException e) {
e.printStackTrace();
}
}
else {
Toast.makeText(getApplicationContext(), "Song is Already Playing", Toast.LENGTH_SHORT).show();
}
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
super.onDestroy();
mp.release();
handler.removeCallbacks(runnable);
}
/// Permanent Notification
private void showNotification() {
nMN = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Notification n = new Notification.Builder(this)
.setContentTitle(songName)
.setContentText(bandName)
.setSmallIcon(R.drawable.ic_bandcamp)
//.addAction(R.drawable.ic_play_arrow_black_24dp, "button1", new pause())
.setOngoing(true)
.build();
nMN.notify(1, n);
}
/// PREPARE SONG TO PLAY //
public class prepare extends AsyncTask {
#Override
protected Object doInBackground(Object[] objects) {
try {
mp.prepare();
PlayCycle();
seekBar.setMax(mp.getDuration());
mp.start();
SongPlaying = songName;
isPlaying=true;
showNotification(); // show notification
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
Toast.makeText(getApplicationContext(),"Song Finished", Toast.LENGTH_LONG).show();
new stop().execute();
}
});
} catch (IOException io){ io.printStackTrace(); }
return null; }}
/// STOP PLAYING SONG //
public static void Stop()
{
mp.reset();
mp.release();
isPlaying=false;
}
public static class stop extends AsyncTask {
#Override
protected Object doInBackground(Object[] objects) {
try {
mp.reset();
mp.release();
isPlaying=false;
} catch (Exception io){ io.printStackTrace(); }
return null; }}
/// PAUSE PLAYING SONG//
public static class pause extends AsyncTask {
#Override
protected Object doInBackground(Object[] objects) {
try {
mp.pause(); }
catch (Exception io){ io.printStackTrace(); }
return null; }}
public static class start extends AsyncTask {
#Override
protected Object doInBackground(Object[] objects) {
try {
mp.start(); }
catch (Exception io){ io.printStackTrace(); }
return null; }}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
// throw new UnsupportedOperationException("Not yet implemented");
return null;
}
Key Point: My application should be capable of running in background.
A rough structure of my application calls is:
HomeActivity(AppCompatActivity) -> MainActivity(AppCompatActivity) -> CameraRecorderService(IntentService) AND SensorService(Service)
Brief Explanation: On a button press in HomeActivity, MainActivity is triggered using Intent. As soon as MainActivity is called, in its onCreate() method, I call the two services i.e. CameraRecorderService and SensorService.
The CameraRecorderService records the video in an infinite loop unless it receives an event from SensorService.
The current application is working completely fine unless the app goes in background, i.e. I press the home button. It gives D/Camera﹕ app passed NULL surface , E/MediaRecorderJNI﹕ Application lost the surface.
The relevant code for MainActivity and CameraRecorderService are:
"MainActivity.java"
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback{
public static SurfaceView mSurfaceView; //declared static so that it can be accessed by Services
public static SurfaceHolder mSurfaceHolder;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSurfaceView = (SurfaceView) findViewById(R.id.surfaceView1);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
Intent intent2 = new Intent(MainActivity.this, SensorService.class);
intent2.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startService(intent2);
Intent intent = new Intent(MainActivity.this, CameraRecorderService.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startService(intent);
ImageButton btnStop = (ImageButton) findViewById(R.id.stop);
btnStop.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
stopService(new Intent(MainActivity.this, CameraRecorderService.class));
stopService(new Intent(MainActivity.this, SensorService.class));
System.exit(0);
}
});
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
"CameraRecorderService.java"
public class CameraRecorderService extends IntentService {
public CameraRecorderService(){
super("CameraRecorderService");
}
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
private static Camera mServiceCamera;
private boolean mRecordingStatus;
private MediaRecorder mMediaRecorder;
static boolean accidentStatus = false;
boolean manualStopStatus = false;
int accidentOnVideoIndex = 0;
#Override
public void onCreate() {
super.onCreate();
mSurfaceView = MainActivity.mSurfaceView; //Getting the surface from Activity
mSurfaceHolder = MainActivity.mSurfaceHolder;
}
#Override
public void onDestroy() {
super.onDestroy();
manualStopStatus = true;
if(mRecordingStatus){
stopRecording();
}
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
protected void onHandleIntent(Intent intent) {
while(!accidentStatus){
int i =1;
while(i < 3) {
if (!accidentStatus && !manualStopStatus) {
accidentOnVideoIndex = i;
startRecording("someName" + i);
try {
Thread.sleep(5000);
if(mRecordingStatus)
stopRecording();
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}else{
break;
}
}
}
if(!manualStopStatus) {
startRecording("someName3");
try {
Thread.sleep(5000);
stopRecording();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public boolean startRecording(String fileName){
try {
mRecordingStatus = true;
mServiceCamera = Camera.open();
Camera.Parameters p = mServiceCamera.getParameters();
final List<Camera.Size> listSize = p.getSupportedPreviewSizes();
Camera.Size mPreviewSize = listSize.get(2);
Log.v(TAG, "use: width = " + mPreviewSize.width
+ " height = " + mPreviewSize.height);
p.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
p.setPreviewFormat(PixelFormat.YCbCr_420_SP);
mServiceCamera.setParameters(p);
mServiceCamera.setDisplayOrientation(90);
try {
mServiceCamera.setPreviewDisplay(mSurfaceHolder);
mServiceCamera.startPreview();
}
catch (IOException e) {
Log.e(TAG, e.getMessage());
e.printStackTrace();
}
mServiceCamera.unlock();
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setCamera(mServiceCamera);
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_480P));
mMediaRecorder.setOutputFile("/somePath/" + fileName + ".mp4");
mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
mMediaRecorder.prepare();
mMediaRecorder.start();
return true;
} catch (IllegalStateException e) {
Log.d(TAG, e.getMessage());
e.printStackTrace();
return false;
} catch (IOException e) {
Log.d(TAG, e.getMessage());
e.printStackTrace();
return false;
}
}
public void stopRecording() {
mRecordingStatus = false;
try {
mServiceCamera.reconnect();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mMediaRecorder.stop();
mMediaRecorder.reset();
mServiceCamera.stopPreview();
mMediaRecorder.release();
mServiceCamera.release();
mServiceCamera = null;
}
public static class MyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
System.out.println("Accident!!");
accidentStatus = true;
}
}
I think the problem is that the SurfaceView is destroyed when Activity goes in onPause() state and as I have used a static SurfaceView it is nullified. And so the CameraRecorderService(IntentService) does not get the value from Activity because it runs on a separate thread.
But how do I solve this problem? As I said, the application works fine in foreground but the main purpose of my application is to run in background. Any suggestions are welcome!
I successfully implemented AdMob interstitial ads into my application but the only problem is that they are not clickable.
Here is my AdMob.java class:
import android.app.Activity;
import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.InterstitialAd;
public class Admob extends AdListener{
private Activity ctx;
//Admob
private InterstitialAd interstitial;
private AdRequest adRequest;
private String unitId;
public static boolean fromAdmob = false;
public Admob(Activity ctx, String unitId)
{
this.ctx = ctx;
this.unitId = unitId;
try{
this.interstitial = new InterstitialAd(this.ctx);
interstitial.setAdUnitId(unitId);
interstitial.setAdListener(this);
adRequest = new AdRequest.Builder().build();
}
catch (Exception e){
e.printStackTrace();
}
}
public void loadAd()
{
try{
interstitial.loadAd(adRequest);
}
catch (Exception e){
e.printStackTrace();
}
}
#Override
public void onAdLoaded() {
try{
fromAdmob = true;
interstitial.show();
}
catch (Exception e){
e.printStackTrace();
}
}
#Override
public void onAdFailedToLoad(int errorCode)
{
}
#Override
public void onAdClosed() {
fromAdmob = false;
}
}
And the MainPageActivity.java file:
public class MainPageActivity extends Activity implements IGameListener, IEventDelegate{
//Tags
private static final String TAG = "bubblesMainPage";
//Context
public static Activity instance;
//Media
private MediaPlayer mp;
//Ads
private Admob admob;
//TapSDK
private Tap tap;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_page_activity);
overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
tr
Tap.establish(this);
tap = new Tap(this, "xxxx");
}
catch (Exception e){
e.printStackTrace();
}
//Admob
this.admob = new Admob(this, "ADMOB_ID");
//Context
instance = this;
//Media
mp = MediaPlayer.create(getApplicationContext(), R.raw.background_music);
mp.setLooping(true);
//Set activity properties
try {
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
} catch (Exception e) {
e.printStackTrace();
}
//Intents & Listeners
final Intent gamePlayActivity = new Intent(this, BubbleShooterActivity.class);
BubbleShooterActivity.listener = this;
//Animations
Animation scaleUpAnim = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.scale_up);
findViewById(R.id.play_button).startAnimation(scaleUpAnim);
//UI Events
findViewById(R.id.play_button).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new Thread(new Runnable() {
#Override
public void run() {
try {
startActivity(gamePlayActivity);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
});
findViewById(R.id.more_games_button).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
tap.showMoreGamesWithViewControllerAndAppID((IEventDelegate)instance);
}
});
}
/*
Game methods - start
*/
#Override
public void onGameStart() {
Log.i(TAG, "onGameStart");
}
#Override
public void onLevelFailed() {
//Level failed window
try{
Intent i = new Intent(this, LostActivity.class);
startActivity(i);
}
catch (Exception e){
e.printStackTrace();
}
Log.i(TAG, "onLevelFailed");
}
#Override
public void onLevelUp() {
Log.i(TAG, "onLevelUp");
if(admob != null){
runOnUiThread(new Runnable() {
#Override
public void run() {
try{
admob.loadAd();
}
catch (Exception e){
e.printStackTrace();
}
try{
Intent i = new Intent(instance, WonActivity.class);
startActivity(i);
}
catch (Exception e){
e.printStackTrace();
}
}
});
}
}
#Override
public void onGameEnd() {
Log.i(TAG, "onGameEnd");
}
/*
TapSDK methods - start
*/
#Override
public void viewDidAppear() {
Log.i(TAG, "TapSDK: viewDidAppear");
}
#Override
public void viewDidDisappear() {
Log.i(TAG, "TapSDK: viewDidDisappear");
}
#Override
public void viewConnectFail(String s) {
Log.i(TAG, "TapSDK: viewConnectFail " + s);
}
#Override
public void conversion() {
Log.i(TAG, "TapSDK: conversion");
}
#Override
public void onOfferComplete(int score) {
Log.i(TAG, "TapSDK: onOfferComplete " + score);
}
/*
Activity methods start
*/
#Override
public void onBackPressed() {
Log.i(TAG, "onBackPressed");
try{
Intent exitScreen = new Intent(this, ExitActivity.class);
startActivity(exitScreen);
}
catch (Exception e){
e.printStackTrace();
Log.e(TAG, "onBackPressed: " + e.getMessage());
}
}
#Override
protected void onStart() {
super.onStart();
// Monitor launch times and interval from installation
RateThisApp.onStart(this);
// If the criteria is satisfied, "Rate this app" dialog will be shown
RateThisApp.showRateDialogIfNeeded(this);
}
#Override
protected void onResume()
{
super.onResume();
if(tap != null)
tap.onResume();
mp.seekTo(0);
mp.start();
}
#Override
protected void onPause()
{
if(tap != null)
tap.onPause();
mp.pause();
super.onPause();
}
#Override
protected void onDestroy()
{
mp.stop();
mp = null;
if(tap != null)
tap.onDestroy();
super.onDestroy();
}
}
I couldn't figure out how to show the interstitial ad when the user levels up and presses the play button (which will lead him to the next level). The interstitial ad show up when he presses the home button which will take him to the MainActivity screen.
Can someone help me to make the ads clickable? Also, any suggestions on how to add the interstitial ad after each completed level? When someone has finished a level and presses the play button, an interstitial ad should appear and when that is closed he should be able to play the next level.
I really appreciate your help!
A number of issues:
Don't call interstitial.show() from onAdLoaded. Call show() when the user presses the play button for your next level (but only if an ad is available).
Get rid of public static Activity instance; Never hold a static reference to an Activity. You will just leak context everywhere.
Instead of calling admob.loadAd() from onLevelUp() call it as soon as you create your Activity (it takes times to load an ad from the network). NB you don't need to call it from runOnUIThread()
Call admob.loadAd() again after each time you show the ad to the user.
I have a huge problem with the bump API on Android. I setup everything like in the example, the first time I start my activity containing the bump code it works great, now if I go back and start it again it just crash due to a Fatal signal error... It happen right after I call the configure of the bump API.
May I need to not call it again ? But there is nothing to check if it already configured or not.
public class BumpActivity extends Activity {
private IBumpAPI api;
private ProgressDialog mDialog;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.bump);
mDialog = ProgressDialog.show(BumpActivity.this, "Preparing bump", "Loading");
bindService(new Intent(IBumpAPI.class.getName()), connection,
Context.BIND_AUTO_CREATE);
IntentFilter filter = new IntentFilter();
filter.addAction(BumpAPIIntents.CHANNEL_CONFIRMED);
filter.addAction(BumpAPIIntents.DATA_RECEIVED);
filter.addAction(BumpAPIIntents.NOT_MATCHED);
filter.addAction(BumpAPIIntents.MATCHED);
filter.addAction(BumpAPIIntents.CONNECTED);
registerReceiver(receiver, filter);
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
#Override
public void onBackPressed(){
Intent resultIntent = new Intent();
setResult(Activity.RESULT_CANCELED, resultIntent);
super.onBackPressed();
}
private final ServiceConnection connection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className, IBinder binder) {
Log.i("BumpTest", "onServiceConnected");
api = IBumpAPI.Stub.asInterface(binder);
new Thread() {
public void run() {
try {
api.configure("9b17d663752843a1bfa4cc72d309339e",
"Bump User");
} catch (RemoteException e) {
Log.w("BumpTest", e);
}
}
}.start();
Log.d("Bump Test", "Service connected");
}
#Override
public void onServiceDisconnected(ComponentName className) {
Log.d("Bump Test", "Service disconnected");
}
};
private final BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
try {
if (action.equals(BumpAPIIntents.DATA_RECEIVED)) {
getUserDetailFromBump(new String(
intent.getByteArrayExtra("data")));
} else if (action.equals(BumpAPIIntents.MATCHED)) {
long channelID = intent
.getLongExtra("proposedChannelID", 0);
Log.i("Bump Test",
"Matched with: "
+ api.userIDForChannelID(channelID));
api.confirm(channelID, true);
Toast toast = Toast.makeText(
getApplicationContext(),
"Matched with: "
+ api.userIDForChannelID(channelID),
Toast.LENGTH_SHORT);
toast.show();
} else if (action.equals(BumpAPIIntents.CHANNEL_CONFIRMED)) {
long channelID = intent.getLongExtra("channelID", 0);
api.send(channelID, CurrentUserManager.getSharedManager()
.getCurrentUser().getUserId().toString().getBytes());
} else if (action.equals(BumpAPIIntents.NOT_MATCHED)) {
Toast toast = Toast.makeText(getApplicationContext(),
"No match", Toast.LENGTH_SHORT);
toast.show();
} else if (action.equals(BumpAPIIntents.CONNECTED)) {
mDialog.dismiss();
api.enableBumping();
}
} catch (RemoteException e) {
}
}
};
public void getUserDetailFromBump(String data) {
Log.i("User Id", data);
LoginRequest login = new LoginRequest(getApplicationContext());
Log.i("Token", login.getArchivedToken());
AsyncHttpClient restRequest = new AsyncHttpClient();
PersistentCookieStore cookie = new PersistentCookieStore(getApplicationContext());
restRequest.setCookieStore(cookie);
RequestParams params = new RequestParams();
params.put("auth_token", login.getArchivedToken());
params.put("user_id", data);
Log.i("Request", "Preparing");
restRequest.get(Constantes.API_URL + "users/show.json", params, new AsyncHttpResponseHandler(){
public void onSuccess(String response) {
Log.i("Reponse", response);
try {
User user = new User(new JSONObject(response));
Log.i("User", user.toString());
//Driver
if (CurrentUserManager.getSharedManager().getCurrentUser().getType() == 1){
CurrentRouteManager.getSharedManager().getCurrentRoute().addPassanger(user);
Intent resultIntent = new Intent(BumpActivity.this, DriverActivity.class);
resultIntent.putExtra("PASSENGER_ADDED", true);
setResult(1, resultIntent);
finish();
}
else{
Intent p = new Intent(BumpActivity.this, RoutePassenger.class);
p.putExtra("driver", user);
startActivity(p);
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void onFailure(Throwable e) {
Log.i("Error", e.toString());
}
});
}
public void onStart() {
Log.i("BumpTest", "onStart");
super.onStart();
}
public void onRestart() {
Log.i("BumpTest", "onRestart");
super.onRestart();
}
public void onResume() {
Log.i("BumpTest", "onResume");
super.onResume();
}
public void onPause() {
Log.i("BumpTest", "onPause");
try {
api.disableBumping();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
super.onPause();
}
public void onStop() {
Log.i("BumpTest", "onStop");
try {
api.disableBumping();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
super.onStop();
}
public void onDestroy() {
Log.i("BumpTest", "onDestroy");
try {
api.disableBumping();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
unbindService(connection);
unregisterReceiver(receiver);
super.onDestroy();
}
}
I finally resolved it few days ago. As I'm not a JAVA expert I think the bug is located within the Bump library.
If you do api.configure when it is already configured it simply crash. So I ended up making a singleton, ensuring that it is called only once
Here is the code
public class BumpConnection {
protected Context context;
private IBumpAPI api;
private static BumpConnection sharedManager;
public static synchronized BumpConnection getSharedManager(Context context) {
if (sharedManager == null) {
sharedManager = new BumpConnection(context);
}
return sharedManager;
}
private BumpConnection(Context context){
this.context = context;
context.bindService(new Intent(IBumpAPI.class.getName()), connection,
Context.BIND_AUTO_CREATE);
}
public IBumpAPI getApi() {
return api;
}
public void setApi(IBumpAPI api) {
this.api = api;
}
private final ServiceConnection connection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className, IBinder binder) {
Log.i("BumpTest", "onServiceConnected");
api = IBumpAPI.Stub.asInterface(binder);
new Thread() {
public void run() {
try {
api.configure("9b17d663752843a1bfa4cc72d309339e",
"Bump User");
} catch (RemoteException e) {
Log.w("BumpTest", e);
}
}
}.start();
Log.d("Bump Test", "Service connected");
}
#Override
public void onServiceDisconnected(ComponentName className) {
Log.d("Bump Test", "Service disconnected");
}
};
}
Use Latest bump api , available at git hub, read the README.md file carefully.
There is clearly mentioned that by using .aidl file (that is available in src folder) first compile it by using command
android update project -t android-15 -l path_to/bump-api-library -p path_to_your_project/
in your terminal..
If you are a Linux user then set path up to platform-tools then use this command with ./adb .
Then refresh the project , set this Library project as library in your test bump project..
Also replace your bumpapi key that you received via email