i my app i am sending an broadcast from the onTaskRemoved() method of a service. But i am not getting the broadcast in the broadcastReciever. This is my code
#Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
Log.e("TaskRemoved","TaskRemoved");
commonSessionManager.setConnected(false);
broadCastUpdate(GymMainActivity.APP_REMOVED_FROM_RECENTS);
}
public void broadCastUpdate(String action){
Intent intent=new Intent();
intent.putExtra(GymMainActivity.APP_REMOVED_FROM_RECENTS,action);
sendBroadcast(intent);
}
private BroadcastReceiver mGattUpdateReciever = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (WRONG_DATA.equalsIgnoreCase(action)) {
Toast.makeText(GymMainActivity.this, "Please measure your vitals again", Toast.LENGTH_SHORT).show();
isFalseDataSent = true;
}
if (ACTION_GATT_CONNECTED.equalsIgnoreCase(action)) {
Toast.makeText(GymMainActivity.this, "connected", Toast.LENGTH_SHORT).show();
runOnUiThread(new Runnable() {
#Override
public void run() {
if (!isFinishing()) {
ShowConnectDialog();
}
}
});
} else if (ACTION_GATT_DISCONNECTED.equalsIgnoreCase(action)) {
Toast.makeText(GymMainActivity.this, "disconnected", Toast.LENGTH_SHORT).show();
} else if (ACTION_DATA_AVAILABLE.equalsIgnoreCase(action)) {
connectDialog.dismiss();
String[] result = intent.getStringArrayExtra(EXTRA_DATA);
for (int i = 0; i < result.length; i++) {
Log.e("result " + i, result[i]);
}
Log.e("isDisplayed", isDisplayed + "");
if (!isDisplayed) {
if (isFalseDataSent) {
mBluetoothController.powerOff();
isFalseDataSent = false;
}
commonSessionManager.setConnected(true);
Intent vitalDataIntent = new Intent(GymMainActivity.this, GymVitalDisplayActivity.class);
vitalDataIntent.putExtra("userDataBundle",userDataBundle());
vitalDataIntent.putExtra("vitalData", result);
startActivity(vitalDataIntent);
finish();
isDisplayed = true;
}
}
if(action.equalsIgnoreCase(APP_REMOVED_FROM_RECENTS)){
Toast.makeText(GymMainActivity.this,"APP_REMOVED_FROM_RECENTS",Toast.LENGTH_SHORT).show();
btnScan.setVisibility(View.VISIBLE);
if(btnConnect.getVisibility()==View.VISIBLE){
btnConnect.setVisibility(View.GONE);
}
if(txtConnected.getVisibility()==View.VISIBLE){
txtConnected.setVisibility(View.GONE);
}
}
}
};
private static IntentFilter makeGattUpdateIntentFilter() {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ACTION_GATT_CONNECTED);
intentFilter.addAction(ACTION_GATT_DISCONNECTED);
intentFilter.addAction(ACTION_DATA_AVAILABLE);
intentFilter.addAction(WRONG_DATA);
intentFilter.addAction(APP_REMOVED_FROM_RECENTS);
return intentFilter;
}
public final static String ACTION_GATT_CONNECTED =
"com.example.demo.le.ACTION_GATT_CONNECTED";
public final static String ACTION_GATT_DISCONNECTED =
"com.example.demo.le.ACTION_GATT_DISCONNECTED";
public final static String ACTION_DATA_AVAILABLE =
"com.example.demo.le.ACTION_DATA_AVAILABLE";
public final static String EXTRA_DATA =
"com.example.demo.le.EXTRA_DATA";
public final static String WRONG_DATA =
"com.example.demo.le.WRONG_DATA";
public final static String APP_REMOVED_FROM_RECENTS="com.example.demo.le.APP_REMOVED_FROM_RECENTS";
i am receiving all the broadcast except APP_REMOVED_FROM_RECENTS.
It may be because you're not setting the action on the intent but as an extra. Change your code to that and see if it works:
public void broadCastUpdate(String action){
Intent intent=new Intent(action);
sendBroadcast(intent);
}
Related
I am trying to understand the difference bwtettn STICKY and NOT_STICKY intent of a service in onStartCommand().
I created the MainActivity and the Service shown in the code below. I expected when I press the button mBtnStopApp, the onDestroy() wil be called and then
I should receive this log ** Log.w(TAG, SubTag.bullet("++++++++ SERVICE IS NOT RUNNING ++++++++")); **
because onStartCommand() returns NOT_STICKY intnet which means, when the App is killed, the service should also be stopped
but that never happens.
what happens is, when i press the button mBtnStopApp, the App is finished but i receive the following log:
** Log.w(TAG, SubTag.bullet("++++++++ SERVICE IS RUNNING ++++++++")); **
please let me know why the service is still running despite it returns START_NOT_STICKY and the App was killed
MainActivity
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private TextView mTv = null;
private Button mBtnStartStickyService = null;
private Button mBtnStartNonStickyService = null;
private Button mBtnStopApp = null;
private Button mBtnStopNonStickyService = null;
private Button mBtnStopStickyService = null;
private ServicesUtils mServiceUtils = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.w(TAG, SubTag.bullet("#onCreate"));
this.mServiceUtils = new ServicesUtils(this);
this.mBtnStartNonStickyService = (Button) findViewById(R.id.btnNonStickyService);
this.mBtnStartStickyService = (Button) findViewById(R.id.btnStickyService);
this.mBtnStopApp = (Button) findViewById(R.id.btnStopApp);
this.mBtnStopNonStickyService = (Button) findViewById(R.id.btnStopNonStickyService);
this.mBtnStopStickyService = (Button) findViewById(R.id.btnStopStickyService);
this.mTv = (TextView) findViewById(R.id.tv);
this.mBtnStartNonStickyService.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ComponentName componentName = startService(setRunningStateForService(NonStickyService.class, "start"));
Log.i(TAG, "#mBtnStartNonStickyService: componentName: " + componentName);
}
});
this.mBtnStopNonStickyService.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ComponentName componentName = startService(setRunningStateForService(NonStickyService.class, "stop"));
Log.i(TAG, "#mBtnStopNonStickyService: componentName: " + componentName);
}
});
this.mBtnStopApp.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
}
private Intent setRunningStateForService(Class<NonStickyService> serviceClass, String state) {
Log.w(TAG, SubTag.bullet("#setRunningStateForService"));
Intent intent = new Intent(this, serviceClass);
intent.putExtra("running", state);
return intent;
}
#Override
protected void onDestroy() {
super.onDestroy();
Log.w(TAG, SubTag.bullet("#onDestroy"));
if (this.isNonStickyServiceRunning()) {
Log.w(TAG, SubTag.bullet("++++++++ SERVICE IS RUNNING ++++++++"));
} else {
Log.w(TAG, SubTag.bullet("++++++++ SERVICE IS NOT RUNNING ++++++++"));
}
}
private boolean isNonStickyServiceRunning() {
ActivityManager manager = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (NonStickyService.class.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
}
code:
public class NonStickyService extends Service {
private static final String TAG = NonStickyService.class.getSimpleName();
private HeavyWorkRunnable mHeavyWorkRunnable = null;
private String running = null;
#Override
public void onCreate() {
super.onCreate();
Log.w(TAG, SubTag.bullet("#onCreate"));
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.w(TAG, SubTag.bullet("#onStartCommand"));
running = intent.getStringExtra("running");
if (running != null && !running.isEmpty() && running.equals("start")) {
this.StartHeavyWorkThread();
}
return Service.START_NOT_STICKY;
}
private void StartHeavyWorkThread() {
Log.w(TAG, SubTag.bullet("#StartHeavyWorkThread"));
this.mHeavyWorkRunnable = new HeavyWorkRunnable();
new Thread(this.mHeavyWorkRunnable).start();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
Log.w(TAG, SubTag.bullet("#onBind"));
return null;
}
#Override
public void onDestroy() {
Log.w(TAG, SubTag.bullet("#onDestroy"));
super.onDestroy();
this.running = "stop";
}
class HeavyWorkRunnable implements Runnable {
int counter = 0;
private Bundle b = null;
public void run() {
Log.w(TAG,SubTag.bullet("#HeavyWorkRunnable"));
while(running.equals("start")) {
b = new Bundle();
b.putInt("what", ++counter);
Log.w(TAG,SubTag.bullet("#HeavyWorkRunnable: counter: " + counter));
Log.w(TAG,SubTag.bullet("#HeavyWorkRunnable: b.getInt('what'): " + b.getInt("what")));
Message msg = handler.obtainMessage();
msg.setData(b);
handler.sendMessage(msg);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Log.i(TAG,SubTag.bullet("NonStickyService will Stop"));
stopSelf();
}
}
android.os.Handler handler = new android.os.Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
int what = msg.getData().getInt("what");
Log.w(TAG,SubTag.bullet("#handler: what: " + what));
}
};
}
I've got a BroadcastReceiver which checks if Internet connection is available then it starts a service which retrieves an ArrayList from the DB:
public class NetworkWatcher extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();
Intent retrieveVehicleList = new Intent(context, RetrieveVehicleListService.class);
if (info != null)
{
if (info.isConnected())
{
context.startService(retrieveVehicleList);
}
else
{
context.stopService(retrieveVehicleList);
}
}
}
}
public class RetrieveVehicleListService extends IntentService
{
private static final int NOTIFICATION_ID = 1;
private NotificationManager mNotificationManager;
private NotificationCompat.Builder builder;
private ArrayList<Vehicle> vehicles;
private void parseVehiclesFromMap(ArrayList vehicles)
{
for (int i = 0; i < vehicles.size(); i++)
{
final Vehicle v = new Vehicle();
HashMap vehicleMap = (HashMap) vehicles.get(i);
v.setPlate(vehicleMap.get("plate").toString());
v.setKm(vehicleMap.get("km") == null ? null : Integer.parseInt(vehicleMap.get("km").toString()));
v.setFuelQuantity(Double.parseDouble(vehicleMap.get("fuel_quantity").toString()));
v.setEffectiveFuelEconomy(Double.parseDouble(vehicleMap.get("fuel_economy").toString()));
v.setInsuranceDate(vehicleMap.get("insurance_date") == null ? null : new LocalDate(vehicleMap.get("insurance_date").toString()));
v.setMatriculationDate(new LocalDate(vehicleMap.get("matriculation_date").toString()));
v.setLatitude(vehicleMap.get("latitude") == null ? null : Double.parseDouble(vehicleMap.get("latitude").toString()));
v.setLongitude(vehicleMap.get("longitude") == null ? null : Double.parseDouble(vehicleMap.get("longitude").toString()));
v.setFuelType(FuelType.fromInt(Integer.parseInt(vehicleMap.get("id_fuel").toString())));
this.vehicles.add(v);
}
}
private void sendRequest(int userID)
{
Response.Listener<String> listener = new Response.Listener<String>()
{
#Override
public void onResponse(String response)
{
try
{
HashMap json = new ObjectMapper().readValue(response, HashMap.class);
String errorCode = json.get("error_code").toString();
switch (errorCode)
{
case "0":
parseVehiclesFromMap((ArrayList) json.get("vehicles"));
break;
default:
// TODO gestire
break;
}
}
catch (IOException e)
{
// TODO gestire
e.printStackTrace();
}
}
};
VehicleListRequest request = new VehicleListRequest(String.valueOf(userID), listener, null);
RequestQueue queue = Volley.newRequestQueue(this);
queue.add(request);
}
#Override
protected void onHandleIntent(Intent intent)
{
SharedPreferences sp = getSharedPreferences(getString(clyky.cartracker.R.string.sharedPreferencesName), Context.MODE_PRIVATE);
int userID = sp.getInt("id_user", SplashActivity.DEFAULT_USER_ID);
if (userID != SplashActivity.DEFAULT_USER_ID)
{
sendRequest(userID);
}
}
public RetrieveVehicleListService()
{
super("RetrieveVehicleList");
vehicles = new ArrayList<>();
}
}
I want my MainActivity gets that ArrayList from RetrieveVehicleListService when the activity is started. How could I do that?
Thanks in advance.
Use LocalBroadcast reciever to send data from service to activity. Add following code to your activty
private BroadcastReceiver BReceiver = new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent) {
//put here whaterver you want your activity to do with the intent received
ArrayList<String> arrayList=intent.getStringArrayListExtra("arrayList");
}
};
protected void onResume(){
super.onResume();
LocalBroadcastManager.getInstance(this).registerReceiver(bReceiver, new IntentFilter("message"));
}
protected void onPause (){
super.onPause();
LocalBroadcastManager.getInstance(this).unregisterReceiver(bReceiver);
}
and use following method to send broadcast from service
private void sendBroadcast (boolean success){
Intent intent = new Intent ("message"); //put the same message as in the filter you used in the activity when registering the receiver
intent.putExtra("success", success);
intent.putStringArrayListExtra("arrayList", arrayList);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
Use Local Broadcast Receiver :
send broadcast using below code
Intent intent = new Intent("YourAction");
Bundle bundle = new Bundle();
bundle .putSerializable("ARRAYLIST",(Serializable)vehicles);
intent.putExtra("BUNDLE",bundle);
intent.putExtras(intent)
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
And receive broadcast in your activity:
private MyBroadcastReceiver myReceiver;
#Override
public void onResume(){
myReceiver = new MyReceiver();
final IntentFilter intentFilter = new IntentFilter("YourAction");
LocalBroadcastManager.getInstance(this).registerReceiver(myReceiver, intentFilter);
}
#Override
public void onPause(){
if(myReceiver != null)
LocalBroadcastManager.getInstance(this).unregisterReceiver(myReceiver);
myReceiver = null;
}
public class MyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Here you have the received broadcast
// And if you added extras to the intent get them here too
// this needs some null checks
Intent intent = getIntent();
Bundle args = intent.getBundleExtra("BUNDLE");
ArrayList<Object> object = (ArrayList<Object>)args.getSerializable("ARRAYLIST");
}
}
I used the BluetoothLeGatt example code to write an app that automatically connects to a bonded BLE peripheral upon launching the app. Now i am trying to display the data from one of the peripheral's characteristic in a textView. The BluetoothLeGatt example code only demonstrates this using ExpandableListView.OnChildClickListener, my app should require no user input and simply get he data from the characteristic. This is what i have so far:
private TextView mConnectionState;
private TextView mDataField;
private String mDeviceName;
private String mDeviceAddress;
private ExpandableListView mGattServicesList;
private BluetoothLeService mBluetoothLeService;
private boolean mConnected = false;
private BluetoothGattCharacteristic mNotifyCharacteristic;
private final String LIST_NAME = "NAME";
private final String LIST_UUID = "UUID";
// Code to manage Service lifecycle.
private final ServiceConnection mServiceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName componentName, IBinder service) {
mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
if (!mBluetoothLeService.initialize()) {
Log.e(TAG, "Unable to initialize Bluetooth");
finish();
}
// Automatically connects to the device upon successful start-up initialization.
mBluetoothLeService.connect(mDeviceAddress);
}
#Override
public void onServiceDisconnected(ComponentName componentName) {
mBluetoothLeService = null;
}
};
// Handles various events fired by the Service.
// ACTION_GATT_CONNECTED: connected to a GATT server.
// ACTION_GATT_DISCONNECTED: disconnected from a GATT server.
// ACTION_GATT_SERVICES_DISCOVERED: discovered GATT services.
// ACTION_DATA_AVAILABLE: received data from the device. This can be a result of read
// or notification operations.
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
mConnected = true;
updateConnectionState(R.string.connected);
mConnectionState.setTextColor(Color.parseColor("#FF17AA00"));
invalidateOptionsMenu();
} else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
mConnected = false;
updateConnectionState(R.string.disconnected);
invalidateOptionsMenu();
clearUI();
} else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
// Show all the supported services and characteristics on the user interface.
//displayGattServices(mBluetoothLeService.getSupportedGattServices());
} else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
displayData(intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_device_control);
final Intent intent = getIntent();
mDeviceName = intent.getStringExtra(EXTRAS_DEVICE_NAME);
mDeviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS);
mConnectionState = (TextView) findViewById(R.id.connection_state);
mDataField = (TextView) findViewById(R.id.data);
Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
#Override
protected void onResume() {
super.onResume();
registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
if (mBluetoothLeService != null) {
final boolean result = mBluetoothLeService.connect(mDeviceAddress);
Log.d(TAG, "Connect request result=" + result);
}
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(mGattUpdateReceiver);
}
#Override
protected void onDestroy() {
super.onDestroy();
unbindService(mServiceConnection);
mBluetoothLeService = null;
}
private void updateConnectionState(final int resourceId) {
runOnUiThread(new Runnable() {
#Override
public void run() {
mConnectionState.setText(resourceId);
}
});
}
private void displayData(String data) {
if (data != null) {
mDataField.setText(data);
}
}
private void clearUI() {
mGattServicesList.setAdapter((SimpleExpandableListAdapter) null);
mDataField.setText(R.string.no_data);
}
private static IntentFilter makeGattUpdateIntentFilter() {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
return intentFilter;
}
Figured it out.
Iterated through the services, then the characteristics after services were discovered.
UUID chara = UUID.fromString("c97433f0-be8f-4dc8-b6f0-5343e6100eb4");
List<BluetoothGattService> servs = mBluetoothLeService.getSupportedGattServices();
for (int i = 0; servs.size() > i; i++) {
List<BluetoothGattCharacteristic> charac = servs.get(i).getCharacteristics();
for (int j = 0; charac.size() > i; i++) {
BluetoothGattCharacteristic ch = charac.get(i);
if (ch.getUuid() == chara) {
mBluetoothLeService.readCharacteristic(ch);
mBluetoothLeService.setCharacteristicNotification(ch, true);
}
}
}
I am working on an Android Application which have an one activity class and service class. In service, Continuous bulk data (1090 bytes) will be received every 10 milliseconds. I need to update the text view continuously with these bulk data. What is recommended way to update Text view from a continuous background service?
Service Class
public class RecepService extends Service {
public static Handler mHandler;
StringBuilder hexstring;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
init();
}
private void init() {
mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
if (msg.what == 0x123) {
byte[] readBuf = (byte[]) msg.obj;
int readBuflen = msg.arg1;
// here will receive 1090 bytes of data
// every 10 milliseconds
Receivepatientattributes(readBuf,readBuflen);
}
}
};
}
public void Receivepatientattributes(byte[] readBuf, int len) {
String total_data = "";
total_data = bytetohex(readBuf, len);
MainActivity.recep.setText(MainActivity.recep.getText().toString() + "\t" +
"" + total_data );
}
String bytetohex(byte[] txt, int len) {
String p="";
byte[] text = new byte[len];
text = txt;
hexstring = new StringBuilder();
for (int j = 0; j < len; j++) {
String hex= Integer.toHexString(0xFF & txt[j]);
if (hex.length()==1) {
hexstring.append("0");
}
hexstring.append(hex+" ");
}
p=p+hexstring.toString();
return p;
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
}
If you want to use Schedule and timer task then you can See My Answer
To solve current issue follow this bellow instructions.
Suppose your activity has a Broadcast Receiver
private BroadcastReceiver mReceiver;
Then you override methods onResume() where your broadcast receiver will be registered and also onPause() where will your receiver be unregistered:
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
IntentFilter intentFilter = new IntentFilter(
"android.intent.action.MAIN");
mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//extract your message from intent
String msg_for_me = intent.getStringExtra("YOUR_MESSAGE");
//log your message value
Log.i("MyTag", msg_for_me);
}
};
//registering your receiver
this.registerReceiver(mReceiver, intentFilter);
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
//unregister your receiver
this.unregisterReceiver(this.mReceiver);
}
Here the broadcast receiver is filtered via android.intent.action.MAIN and from Service the message will BroadCast using this filter
Now your Method Receivepatientattributes will like this :
public void Receivepatientattributes(byte[] readBuf, int len) {
String total_data = "";
total_data = bytetohex(readBuf, len);
Intent i = new Intent("android.intent.action.MAIN").putExtra("YOUR_MESSAGE", total_data);
this.sendBroadcast(i);
}
Thats it. :)
User LocalBroadcastManager
public void Receivepatientattributes(byte[] readBuf, int len) {
String total_data = "";
total_data = bytetohex(readBuf, len);
Intent intent = new Intent("update-text");
// add data
intent.putExtra("message", total_data);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
In MainActivity
#Override
public void onResume() {
super.onResume();
// Register mMessageReceiver to receive messages.
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
new IntentFilter("update-text"));
}
private boolean mCanBeUpdated = true;
private static final int ONE_SEC = 1000; //ms
private static final int RECEPTION_SPEED = 10; //ms
private static final int CYCLES = (int) (ONE_SEC / RECEPTION_SPEED);
private int mCurrentCycle = -1;
private String mMsgCache = "";
// handler for received Intents for the "update-text" event
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Extract data included in the Intent
String message = intent.getStringExtra("message");
Log.d("receiver", "Got message: " + message);
mMsgCache = mMsgCache + "\t" + message;
if (mCanBeUpdated) {
// No problem updating UI here, refer --> http://stackoverflow.com/a/5676888/1008278
final Handler handler = new Handler(context.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
MainActivity.recep.append(mMsgCache);
mMsgCache = "";
}
});
mCanBeUpdated = false;
} else if (mCurrentCycle >= CYCLES) {
mCurrentCycle = -1;
mCanBeUpdated = true;
} else {
mCurrentCycle++;
}
}
};
#Override
protected void onPause() {
// Unregister since the activity is not visible
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
super.onPause();
}
Reference
You can use Timer for Continously updating your textview.
Set value in preferences every time when your service is running with the latest value.
Now in Timer get that value from preferences and update your TextView with that value.
Here is some code :
class UpdateTimeTask extends TimerTask {
public void run() {
textview.setText("updated value");
}
}
Set in onCreate ();
Timer timer = new Timer();
UpdateTimeTask UpdateTimeTask = new UpdateTimeTask ();
timer.schedule(UpdateTimeTask, 1000);
Use handler beacuse A Handler allows communicating back with UI thread from other background thread.
boolean handlerStop = false;
void handleHandler(){
Handler handler =new Handler();
final Runnable r = new Runnable() {
public void run() {
handler.postDelayed(this, 30000);
if(!handlerStop) {
updateTextView() //update your text with other thread like asyncronous thread
}
}
};
handler.postDelayed(r, 0000);
}
#Override
public void onResume() {
super.onResume();
handlerStop=false;
handleHandler();
}
#Override
public void onPause() {
super.onPause();
handlerStop=true;
handleHandler();
}
#Override
public void onStop() {
super.onStop();
handlerStop=true;
handleHandler();
}
I code a service to subscribe message from mqtt server. Service auto reconnect when internet connection on/off.
This code:
public class NotificationService extends Service{
private Handler connectBrokerHandler;
private ConnectBrokerTimerTask connectBrokerTimerTask;
private Timer connectBrokerTimer;
private MqttAndroidClient androidClient;
private MqttConnectOptions connectOptions;
private MemoryPersistence memPer;
private IMqttToken connectToken;
private CustomActionListener customActionListener;
private Context context;
private String CLIENT_STATUS = CLIENT_INIT;
private static final String TAG = "NotificationService";
private static final String USER_NAME = "chuxuanhy";
private static final String PASS_WORD = "0936160721";
private static final String URL_BROKER = "tcp://ntm.diyoracle.com:1883";
private static final String TOPIC_STAFF = "PROSHIP_STAFF";
private static final String DEVICE_ID = "FUCKYOU_002";
private static final int CONNECTION_TIMEOUT = 60;
private static final int KEEP_ALIVE_INTERVAL = 60*60;
private static final int TRY_CONNECTION_DELAY = 30; //seconds
private static final String CLIENT_INIT = "CLIENT_INIT";
private static final String CLIENT_CONNECTION_BROKER_START = "CLIENT_CONNECTION_BROKER_START";
private static final String CLIENT_CONNECTION_BROKER_FAIL = "CLIENT_CONNECTION_BROKER_FAIL";
private static final String CLIENT_CONNECTION_BROKER_SUCCESS = "CLIENT_CONNECTION_BROKER_SUCCESS";
private static final String CLIENT_LOST_CONNECTION = "CLIENT_LOST_CONNECTION";
private static final String CLIENT_SUBSCRIBE_TOPIC_START = "CLIENT_SUBSCRIBE_TOPIC_START";
private static final String CLIENT_SUBSCRIBE_TOPIC_FAIL = "CLIENT_SUBSCRIBE_TOPIC_FAIL";
private static final String CLIENT_SUBSCRIBE_TOPIC_SUCCESS = "CLIENT_SUBSCRIBE_TOPIC_SUCCESS";
private IntentFilter FilterNetwork;
private BroadcastReceiver ReceiverCheckInternet = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(isOnline()){
if(CLIENT_STATUS == CLIENT_LOST_CONNECTION || CLIENT_STATUS == CLIENT_CONNECTION_BROKER_FAIL || CLIENT_STATUS == CLIENT_SUBSCRIBE_TOPIC_FAIL) {
ConnectBroker();
}
}
}
};
private class ConnectBrokerTimerTask extends TimerTask{
#Override
public void run() {
connectBrokerHandler.post(ConnectBrokerRunable);
}
}
private Runnable ConnectBrokerRunable = new Runnable() {
#Override
public void run() {
ConnectBroker();
}
};
public boolean isOnline() {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
return netInfo != null && netInfo.isConnectedOrConnecting();
}
public void RestartNotificationService(){
Intent restartServiceIntent = new Intent(getApplicationContext(), this.getClass());
restartServiceIntent.setPackage(getPackageName());
PendingIntent restartServicePendingIntent = PendingIntent.getService(getApplicationContext(), 1, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmService.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + 1000, restartServicePendingIntent);
}
public void createNotification(String title, String body) {
Intent intent = new Intent(this, NotificationReceiver.class);
PendingIntent pIntent = PendingIntent.getActivity(this, (int) System.currentTimeMillis(), intent, 0);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getApplicationContext());
Notification notification = mBuilder.setSmallIcon(R.drawable.train).setTicker(title).setWhen(0)
.setAutoCancel(true)
.setContentTitle(title)
.setStyle(new NotificationCompat.BigTextStyle().bigText(body))
.setContentIntent(pIntent)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setVibrate(new long[]{1000, 1000})
.setLargeIcon(BitmapFactory.decodeResource(getApplicationContext().getResources(), R.mipmap.ic_launcher))
.setContentText(body).build();
Random random = new Random();
int m = random.nextInt(9999 - 1000) + 1000;
NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(m, notification);
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onTaskRemoved(Intent rootIntent) {
try{
RestartNotificationService();
}catch (Exception e){
e.printStackTrace();
}
super.onTaskRemoved(rootIntent);
}
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(ReceiverCheckInternet);
Log.e(TAG, "onDestroy");
try{
if(androidClient.isConnected()){
this.androidClient.unsubscribe(TOPIC_STAFF);
this.androidClient.disconnect();
this.androidClient = null;
}
}catch (Exception e){
e.printStackTrace();
}
}
private void ConnectBroker(){
try {
CLIENT_STATUS = CLIENT_CONNECTION_BROKER_START;
connectToken = this.androidClient.connect(connectOptions,null,customActionListener);
}catch (Exception e){
//e.printStackTrace();
Log.e(TAG, "ConnectBroker Fail Exception");
}
}
private void SubscribeBrokerTopic(String topic){
try {
CLIENT_STATUS = CLIENT_SUBSCRIBE_TOPIC_START;
androidClient.subscribe(topic, 0, null, customActionListener);
} catch (Exception e) {
//e.printStackTrace();
Log.e(TAG, "SubscribeBrokerTopic Fail Exception");
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("NOTIFI","CALL ME onStartCommand");
this.connectBrokerHandler = new Handler();
this.connectBrokerTimer = new Timer();
this.connectBrokerTimerTask = new ConnectBrokerTimerTask();
this.customActionListener = new CustomActionListener();
this.memPer = new MemoryPersistence();
this.connectOptions = new MqttConnectOptions();
this.connectOptions.setCleanSession(true);
this.connectOptions.setUserName(USER_NAME);
this.connectOptions.setPassword(PASS_WORD.toCharArray());
this.connectOptions.setConnectionTimeout(CONNECTION_TIMEOUT);
this.connectOptions.setKeepAliveInterval(KEEP_ALIVE_INTERVAL);
this.androidClient = new MqttAndroidClient(getApplicationContext(),URL_BROKER,DEVICE_ID,memPer);
this.androidClient.setCallback(new CustomCallBack());
this.androidClient.setTraceCallback(new CustomTraceHandler());
//this.androidClient.
this.FilterNetwork = new IntentFilter();
this.FilterNetwork.addAction("android.net.conn.CONNECTIVITY_CHANGE");
registerReceiver(ReceiverCheckInternet, FilterNetwork);
//this.androidClient.registerResources(getApplicationContext());
ConnectBroker();
return START_NOT_STICKY;
}
private class CustomTraceHandler implements MqttTraceHandler{
#Override
public void traceDebug(String source, String message) {
Log.e(TAG,"CustomConnectHandler - traceDebug\n"+source+" - "+message);
}
#Override
public void traceError(String source, String message) {
Log.e(TAG, "CustomConnectHandler - traceError\n" + source + " - " + message);
}
#Override
public void traceException(String source, String message, Exception e) {
Log.e(TAG, "CustomConnectHandler - traceException\n" + source + " - " + message);
e.printStackTrace();
}
}
private class CustomCallBack implements MqttCallback{
#Override
public void connectionLost(Throwable throwable) {
CLIENT_STATUS = CLIENT_LOST_CONNECTION;
if(!isOnline()){
Log.e(TAG, "ConnectCallBack connectionLost - No Internet Connection ");
}else {
//throwable.printStackTrace();
}
}
#Override
public void messageArrived(String s, MqttMessage mqttMessage) throws Exception {
Log.e(TAG,"ConnectCallBack messageArrived\n"+s+" - "+mqttMessage.toString());
createNotification(s, mqttMessage.toString());
}
#Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
Log.e(TAG, "ConnectCallBack deliveryComplete");
}
}
private class CustomActionListener implements IMqttActionListener {
#Override
public void onSuccess(IMqttToken iMqttToken) {
if (CLIENT_STATUS == CLIENT_CONNECTION_BROKER_START) {
CLIENT_STATUS = CLIENT_CONNECTION_BROKER_SUCCESS;
if (iMqttToken.getTopics() == null) {
SubscribeBrokerTopic(TOPIC_STAFF);
}
Log.e(TAG, "CustomActionListener - CONNECT BROKER onSuccess");
} else if (CLIENT_STATUS == CLIENT_SUBSCRIBE_TOPIC_START) {
CLIENT_STATUS = CLIENT_SUBSCRIBE_TOPIC_SUCCESS;
Log.e(TAG, "CustomActionListener - SUBSCRIBE TOPIC onSuccess");
}
}
#Override
public void onFailure(IMqttToken iMqttToken, Throwable throwable) {
if (CLIENT_STATUS == CLIENT_CONNECTION_BROKER_START) {
CLIENT_STATUS = CLIENT_CONNECTION_BROKER_FAIL;
Log.e(TAG, "CustomActionListener - CONNECT BROKER onFailure ");
} else if (CLIENT_STATUS == CLIENT_SUBSCRIBE_TOPIC_START) {
CLIENT_STATUS = CLIENT_SUBSCRIBE_TOPIC_FAIL;
Log.e(TAG, "CustomActionListener - SUBSCRIBE TOPIC onFailure ");
}
if (isOnline()) {
throwable.printStackTrace();
//connectBrokerTimer.scheduleAtFixedRate(connectBrokerTimerTask, 5000, TRY_CONNECTION_DELAY * 1000);
}else {
Log.e(TAG, "CustomActionListener onFailure - No Internet Connection ");
}
}
}
}
But i have a problem, every time internet connection lost, i reconnect server, callback call again.
Example:
Log.e(TAG, "ConnectCallBack connectionLost - No Internet Connection ");
call twice, 3 time, 4 time every disconnect internet
Sorry my english not good, thank for help.
Don't handle the re-connection manually, newer version of paho has option to auto reconnect in MqttConnectOptions class.
compile 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.1'
compile 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'