retry with varying intervals on each time - java

I am working on a ble-android communication app. I am getting TYPE_GATT_ERROR sometimes when I try to read values from ble device. So I like to retry the scan and reading values each time the TYPE_GATT_ERROR is seen. first time when it happens, I want to start the scan again after 30secs and if that time also if the code reaches TYPE_GATT_ERROR segment, It should start scan again after 1 min and third time if it reaches the error segment, It should rescan with time interval 2mins. How can I do that with the below code segment? The Elseif case with the TYPE_GATT_ERROR condition is where I want to implement the retry algorithm.
private final BroadcastReceiver bleServiceReceiver = new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent){
String type = intent.getExtras().getString(
BleReceivedService.EXTRA_TYPE);
if (BleReceivedService.TYPE_GATT_CONNECTED.equals(type)){
Log.d(TAG, " MYTAG DashBoard onReceive TYPE_GATT_CONNECTED");
if (BleReceivedService.getGatt() != null){
BleReceivedService.getGatt().discoverServices();
Log.d(TAG, " Connect Device");
stopScan();
}
} else if (BleReceivedService.TYPE_GATT_DISCONNECTED.equals(type)){
Log.d(TAG, " MYTAG Disconnect Device");
Log.d(TAG, " MYTAG DashBoard onReceive TYPE_GATT_DISCONNECTED");
BleReceivedService.getInstance().disconnectDevice();
if(isScanning) {
Log.d("ScanCheck","Scanning after disconnection");
stopScan();
}
} else if (BleReceivedService.TYPE_GATT_ERROR.equals(type)) {
Log.d(TAG, " MYTAG DashBoard onReceive TYPE_GATT_ERROR");
//here i want to call startscan() method in the above described fashion
} else {
//do someting
}
}
};
Please help me with the code to achieve this.
Thanks in advance.

Related

data is not received from intent

I am working with BLE. I am trying to use intend to send rssi value from one activity to another.
Activity 1, when ever there is a change in the rssi signal, I send the values over, shown below:
#Override
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
//first logcat
Log.d("BLE_Strength_connected", String.format("BluetoothGatt ReadRssi[%d]", rssi));
Intent i = new Intent(Activity1.this, Activity2.class);
i.putExtra("key",rssi);
startActivity(i);
}
}
};
Activity 2:
In the oncreate() method, I started a handler, and it reads the data every second, I have the following:
mIntent = getIntent();
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
try {
mHandler.postDelayed(this, 1000);
// if (mIntent != null) {
int value = mIntent.getIntExtra("key", 0);
Log.d("retrieve_RSSI", "value:" + value);
//The key argument here must match that used in the other activity
// }
}catch (Exception e) {
}
}
}, 1000);
My logcat on Activity 1 is constantly prints the rssi signal, but the logcat on activity 2 only prints zero. I am wondering why I can't receive any values in activity 2?
Your mIntent variable will always refer to the same Intent object, so when you extract the "key" extra from it, you will of course always get the same value.
You must make sure you handle new incoming intents. See for example http://m.helloandroid.com/tutorials/communicating-between-running-activities how to do that.

Cant get ProgressDialog to show up in android

I cant get a progress dialog to show when I need it to. I have tried putting it in my asyncTask the ui class and the its own thread that runs on the ui and none have worked. Can anyone help me?
the method where the progressDialog method is called:
public void shareTest(View view){ //method called to jump to share activity if criteria matched
if(checkInputs()) { //call to check inputs
Share start = new Share();
boolean isConnected=start.connectToServer(); //connectToServer
Intent intent = new Intent(HomeScreen.this, Share.class); //create intent to move to share class from this activity
startProgressDialog();
if (isConnected) { //check to see if isconnected was succesful
if (Share.matchFound ){ //check to see if a match was found
progress.dismiss();
startActivity(intent); //if true jump to share activity
} else {
while (!Share.timedOut) { //While the time has not timedOut
if (Share.matchFound) { //if a share has been found
startActivity(intent); //start share activity
break; //if true then break
}
}
if (Share.timedOut) {
//send an notice that a match wasn't found
sendToast(getString(R.string.noShare)); //if not true then send Toast
}
}
}
else sendToast(getString(R.string.errServCon)); //if connection to server failed then send toast
}
}
this is the method:
void startProgressDialog() {
new Thread(new Runnable() {
#Override
public void run() { //creates a new runnable thread
// Issue command() on a separate thread
while (!Share.matchFound) { //while havent been asked to disconnect //if a new location has been recieved
activity.runOnUiThread(new Runnable() {
#Override
public void run() { //run on the ui thread act
progress.show(); //call the method that does the update
}
});
}
progress.dismiss();
}
}).start();
}
Declare a global variable like this:
ProgressDialog progress;
Wherever you want to show the progress, paste this code:
progress = ProgressDialog.show(this, "Please wait",
"Loading..", true);
When you are done, simply dismiss it:
progress.dismiss();

EditText value in a Service

I'm building an application in which I use a service to create a background process. but I have a problem.
I use an EditText where the user enters a URL, then I will use that url in the service for check the connection to a website every X minutes. But if the user closes the application, the background process crash because the value of the EditText became Null, and logcat give me null pointer exceptions. I pass the value from the activity to the service with an intent, MainActivity code below:
public void onClickReadWebPage(View v)
{
if(address.getText().toString().trim().length() == 0)
{
Toast.makeText(getApplicationContext(), "URL String empty.", Toast.LENGTH_LONG).show();
}
else
{
time = String.valueOf(address.getText());
i=new Intent(MainActivity.this,MyService.class);
p=PendingIntent.getService(MainActivity.this, 0, i, 0);
i.putExtra("Address", time);
//start the service from here //MyService is your service class name
startService(i);
}
and this is the service code:
#Override
public void onStart(Intent intent, int startId)
{
Address = intent.getStringExtra("Address");
DownloadWebPageTask task = new DownloadWebPageTask();
task.execute(Address);
if(report == "false")
{
//do my stuff
}
else
{
//do my stuff
}
}
Any suggestion?
Just save the value of ediText in SharedPreferences and then retrieve them in your service
.See
How to use SharedPreferences in Android to store, fetch and edit values
Also Problems using SharedPreferences on a Service (getPreferences doesn't exist on a service)

Android READ_PHONE_STATE Event

Can i use loops in READ_PHONE_STATE event?
I want to work loop when phone started ringing to end ringing.
also same the case of user start calling to disconnect the call.
This is my broadcast receiver class
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
while (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_RINGING)) {
//wate for user shaking the phone
//call ansered
}
while (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
//do something while phone answered
//I want to work something during the calling time
}
if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_IDLE) {
//do some
}
}
}
You've already done all the necessary research, it's just probably not 'looping' that you want to do.
What you need is to start something when the phone rings, and stops when it stops ringing. Same for in-call.
To handle events while the phone is ringing, start doing something on CALL_STATE_RINGING, then wait for either CALL_STATE_OFFHOOK or CALL_STATE_IDLE to know when ringing has stopped.
Same for while the user is making a call: start something when your receiver receives CALL_STATE_OFFHOOK and stop when it receives CALL_STATE_IDLE.
I would have your BroadcastReceiver send a message (or call a function) in your UI thread to do what you need to do, then notify when call state has changed.
You don't need to be looping during those intervals. You just want to start/stop doing something at the right time. You can always put some backup security (eg: if phone rang and nothing happened for 3 mins, I stop doing something) to make sure you won't keep running things when you don't want to be.
You can detect when an incoming call is picked/dropped, and when an outgoing call is started/stopped so implement your "looping" logic in the associated callbacks. I've included comments in the code below:
public abstract class PhoneCallReceiver extends BroadcastReceiver {
static CallStartEndDetector listener;
#Override
public void onReceive(Context context, Intent intent) {
savedContext = context;
if(listener == null){
listener = new CallStartEndDetector();
}
TelephonyManager telephony = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
telephony.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
}
public class CallStartEndDetector extends PhoneStateListener {
int lastState = TelephonyManager.CALL_STATE_IDLE;
boolean isIncoming;
public PhonecallStartEndDetector() {}
//Incoming call- IDLE to RINGING when it rings, to OFFHOOK when it's answered, to IDLE when hung up
//Outgoing call- from IDLE to OFFHOOK when dialed out, to IDLE when hunged up
#Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
if(lastState == state){
//No change
return;
}
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
isIncoming = true;
//incoming call started
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
//Transition of ringing->offhook are pickups of incoming calls. Nothing down on them
if(lastState != TelephonyManager.CALL_STATE_RINGING){
isIncoming = false;
//outgoing call started
}
break;
case TelephonyManager.CALL_STATE_IDLE:
//End of call(Idle). The type depends on the previous state(s)
if(lastState == TelephonyManager.CALL_STATE_RINGING){
// missed call
}
else if(isIncoming){
//incoming call ended
}
else{
//outgoing call ended
}
break;
}
lastState = state;
}
}
}

Android media player stop playing while in background

I'm making music player app with simple functionality. But when I listen music on my phone with Android 6, sometimes music stops playing until I turn on display again with power button. Then next song is playing, so it seems like it's problem with loading next song. I tried to write new app just to test it out, for this purpose I used this tutorial:
https://code.tutsplus.com/tutorials/background-audio-in-android-with-mediasessioncompat--cms-27030
To this example I added ArrayList with paths to songs. In mediaPlayer onCompletionListener I increase track counter and load new song to media player.
My code:
private void initMediaPlayer() {
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setVolume(1.0f, 1.0f);
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer)
{
onTrackCompletion();
}
});
private void onTrackCompletion()
{
NextTrack();
Play();
}
private void NextTrack()
{
playlistPosition++;
if (playlistPosition == playlists.get(playlistCurrent).size){
playlistPosition = 0;
}
sendAction(ACTION_TRACK_NEXT);
if(mMediaPlayer.isPlaying()){
Pause();
}
loadSong();
Play();
}
private void loadSong()
{
String path = playlists.get(playlistCurrent).getPath(playlistPosition);
if(path == null || path == "")
{
return;
}
try
{
try
{
mMediaPlayer.setDataSource(path);
} catch( IllegalStateException e ) {
mMediaPlayer.release();
initMediaPlayer();
mMediaPlayer.setDataSource(path);
}
initMediaSessionMetadata();
} catch (IOException e) {
return;
}
try {
mMediaPlayer.prepare();
} catch (IOException e) {}
sendTrackData();
}
I don't know anymore why this doesn't work. In manifest I have WAKE_LOCK permission. I also set wake lock for Media player.
Edit:
Today I tried to move loading song into onPlayFromMediaId. I made broadcast from AutoActivity where is Media player to Main Activity and send back onPlayFromMediaId with path to song. But seems like this doesn't work either.I also find out that changing volume with buttons also wake up app.
Edit2:
I made many tests and added debug string in many places in code. And I found out that app stops at mediaplayer.prepare() until I trigger any action on phone (turn on display, volume up/down, click headset button). But I don't know how to fix this bug. I tried to use prepareAsync, but didn't help.
Unless you use foreground service, the system will kill your process and mediaplayer will stop.
below is a part from from a foreground service ( notification example).
builder.setContentTitle(aMessage) // required
.setSmallIcon(R.mipmap.ic_launcher)
.setContentText(this.getString(R.string.app_name)) // required
.setAutoCancel(false)
.setContentIntent(pendingIntent)
.setVibrate(new long[]{0L})
.setPriority(Notification.PRIORITY_HIGH);
int mId = 1489;
startForeground(mId, builder.build());
The above code is tested and working fine.

Categories

Resources