I am working on an android app with calling webservice when it has internet by using service and broadcast receivers below is my code:
public class YourService extends IntentService {
private static String TAG = YourService.class.getSimpleName();
private MyThread mythread;
public boolean isRunning = false;
JSONArray SaveOrderDart,SaveOrderDetails,UpdateDart,updateOrderDetails;
private static String urlDartorder= Config.url+"SaveDartDetails";
private static String urlupdateOrderDetails= Config.url+"UpdateOrderDetails";
private static String urlSaveOrderDetails= Config.url+"SaveOrderDetails";
private static String urlDartupdate= Config.url+"UpdateDartDetails";
DartDatabase ddb;
OrderDatabase ord;
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
* #param name Used to name the worker thread, important only for debugging.
*/
public YourService(String name) {
super(name);
}
#Override
public void onCreate() {
super.onCreate();
mythread=new MyThread();
}
public YourService()
{
super("call webservice");
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
Bundle extras = intent.getExtras();
boolean isNetworkConnected = extras.getBoolean("isNetworkConnected");
// your code
if(isNetworkConnected){
if(!isRunning){
mythread.start();
isRunning = true;
}
Log.e("TAG", "Yes");
}
else {
if (mythread != null) {
isRunning = false;
mythread.interrupt();
}
//mythread.stop();
}
}
#Override
public void onDestroy() {
super.onDestroy();
if(!isRunning){
mythread.start();
isRunning = true;
}
}
My broadcastreceiver
public class ConnectivityChangeReceiver extends BroadcastReceiver {
boolean mLastState =false;
#Override
public void onReceive(Context context, Intent intent) {
// Explicitly specify that which service class will handle the intent.
ComponentName comp = new ComponentName(context.getPackageName(),
YourService.class.getName());
//mLastState = true;
intent.putExtra("isNetworkConnected", isConnected(context));
context.startService((intent.setComponent(comp)));
}
public boolean isConnected(Context context) {
ConnectivityManager connectivityManager = ((ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE));
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
return networkInfo != null && networkInfo.isAvailable() && networkInfo.isConnected();
}
}
my purpose is when internet is present i want to call webservice not present then stop the thread and service but by this code i can't stop the service i don't no why please help me!
but i can't stop thread please help me!
Related
I register a broadcast on runtime to receive "android.net.wifi.WIFI_STATE_CHANGED"
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.net.wifi.WIFI_STATE_CHANGED");
broadcastReceiverAction = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.net.wifi.WIFI_STATE_CHANGED")) {
/*I get this action as soon as calling registerReceiver(broadcastReceiverAction, intentFilter);*/
}
}
}
registerReceiver(broadcastReceiverAction, intentFilter);
Issue: This gets the broadcast action as soon as registering the receiver.
I got this on Android API 26 & Higher Which I can not declare "android.net.wifi.WIFI_STATE_CHANGED" in Manifest. (No Longer Supported by Android System)
To check network connectivity state change you can do it programmatically. It supports API 21+.
public class ConnectionStateMonitor extends ConnectivityManager.NetworkCallback {
public final String TAG = ConnectionStateMonitor.class.getSimpleName();
private boolean isLost = false;
final NetworkRequest networkRequest;
Context context;
private ConnectionStateMonitor instance;
private boolean isLost = false;
private ConnectionStateMonitor() {
networkRequest = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.build();
}
public synchronized ConnectionStateMonitor getInstance() {
if (instance == null) {
instance = new ConnectionStateMonitor();
}
return instance;
}
public void enable(Context context) {
try {
if (context == null) return;
this.context = context;
ConnectivityManager connectivityManager =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
connectivityManager.registerNetworkCallback(networkRequest, this);
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onAvailable(Network network) {
Log.i(TAG, "onAvailable called " +
network.toString());
if (isLost) {
isLost = false;}
// when network available called it
}
#Override
public void onLost(Network network) {
super.onLost(network);
isLost = true;
// when network lost called it
Log.i(TAG, "onLost called ");
}
}
[Simple Solution]
Problem is Sticky Broadcasts which trigger at the moment of registration.
To avoid this I simply add another parameter to restrict the process.
I defined a static variable
public static boolean triggerBroadcast = false;
Then I change it to after registering the broadcast by few second delay.
registerReceiver(broadcastReceiverAction, intentFilter);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
triggerWifiBroadcast = true;
}
}, 3000);
Then onReceive() I compare intent.getAction with this
if (intent.getAction().equals("android.net.wifi.WIFI_STATE_CHANGED") && triggerBroadcast ) {
//
}
Then you can change it to false whenever decide to unregister the broadcast receiver.
I have a media player service, and I need the fragment UI to be updated or in sync with the service data.
Currently I am using a Broadcast to send and receive the data. But my question is, is there a better way to do this in android?
In Service:
private void startBroadcast() {
if(broadcastThread!= null && !broadcastThread.isInterrupted())
broadcastThread.interrupt();
broadcastThread = new Thread(){
#Override
public void run() {
try {
while(!isInterrupted()) {
Intent intent = new Intent(FILTER);
intent.putextra("foo",1);
sendBroadcast(intent);
sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
broadcastThread.start();
}
In Fragment:
private BroadcastReceiver serviceReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
int foo= intent.getIntExtra("foo", 0);
// bla bla
}
};
.
.
#Override
public void onResume() {
super.onResume();
Objects.requireNonNull(getActivity()).registerReceiver(serviceReceiver ,FILTER);
}
you can use Bind Service to connect service to your activity
and after that update all of your fragment with that
bindService(oIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
private ServiceConnection mServiceConnection =
new ServiceConnection(){
public void onServiceConnected(
ComponentName cName, IBinder service){
MyBinder binder = (MyService.MyBinder) service;
mService = binder.getService();
// Get a reference to the Bound Service object.
mServiceBound = true;
}
public void onServiceDisconnected(ComponentName cName){
mServiceBound= false;
}
};
and after you want change your activity you should unbind connection
if (mServiceBound){
unbindService(mServiceConnection);
mServiceBound = false;
}
I had a similar problem with MediaPlayer, I had to update UI component in every seconds, too.
I used Runnable + Handler combo, like this:
//...
private Handler mHandler;
private Runnable mSeekBarUpdater
//...
#Override
protected void onStart() {
super.onStart();
//...
int result;
// ...
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
mMediaPlayer.setOnCompletionListener(this);
// Start playing and set isPlaying to true. This attribute is required on rotating screen
mMediaPlayer.start();
isPlaying = true;
/**
* Preparing Handler object and a Runnable in order to
* update SeekBar status
*/
if (mHandler == null) {
mHandler = new Handler();
}
if (mSeekBarUpdater == null) {
mSeekBarUpdater = new Runnable() {
#Override
public void run() {
if (mMediaPlayer != null && mHandler != null) {
if (mMediaPlayer.isPlaying()) {
// Refreshing SeekBar position
mCurrentPosition = mMediaPlayer.getCurrentPosition();
mSeekBar.setProgress(mCurrentPosition);
// .. put your code here in order to refresh your UI components
}
// Refreshing on every second
mHandler.postDelayed(this, 1000);
}
}
};
}
PlayerActivity.this.runOnUiThread(mSeekBarUpdater);
}
}
I have created one IntentService to send local data to the server.
I am calling this service from two different broadcast receivers.
1) When from Connectivity change receiver.
2) on 12 am with alarm manager
Its working fine when an app is open.
But not working when an app is closed.
Below is my IntentService code.
public class ExpertEventService extends IntentService {
#Inject
Context context;
#Inject
Realm realm;
public ExpertEventService() {
super("ExpertEventService");
Log.e("expertEvent", "service constructor");
// Toothpick.inject(this, Toothpick.openScope(Constants.APPSCOPENAME));
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
Toothpick.inject(this, Toothpick.openScope(Constants.APPSCOPENAME));
Log.e("expertEvent", "service started");
RealmResults<AskExpertEventModel> results = realm.where(AskExpertEventModel.class).findAll();
List<AskExpertEventModel> requestList = realm.copyFromRealm(results);
String language = realm.where(LanguageStore.class).equalTo(LanguageStore.ISSELECTED, true).findAll().first().getCode();
String appInstanceCode = Preferences.getAppInstanceCode(context);
String token = Preferences.getToken(context);
Api.userManagement(context).expertEvent(appInstanceCode, token, language, requestList)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(new ApiSuccess<EventResponse>() {
#Override
public void call(EventResponse eventResponse) {
Log.e("expertEvent", eventResponse.getStatus());
if (eventResponse.getStatus().equalsIgnoreCase(Constants.Status.STATUS_SUCCESS)) {
Log.e("expertEvent", "sucess");
new RealmDB().deleteEvent();;
}
}
}, new ApiFail() {
#Override
public void httpStatus(HttpErrorResponse response) {
Log.e("expertEvent", response.getError());
}
#Override
public void noNetworkError() {
Log.e("expertEvent", "no network connection");
}
#Override
public void unknownError(Throwable e) {
Log.e("expertEvent", e.getMessage());
}
});
}
}
1) Receiver called when connectivity change
public class NetworkStateReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.e("expertEvent", "Connectivity changed");
ConnectivityManager cm = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();
if (info != null) {
if (info.isConnected()) {
//start service
Log.e("expertEvent", "Connected ");
Intent serviceIntent = new Intent(context,
ExpertEventService.class);
context.startService(serviceIntent);
}
} else {
Log.e("expertEvent", "not connected");
}
}
}
2) Execute when 12 am
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//call service
Log.e("alarmreceiver","in alarm receiver");
Intent serviceIntent = new Intent(context, ExpertEventService.class);
context.startService(serviceIntent);
}
}
public class NetworkConnectivityListener {
private static final String TAG = "NetworkConnectivityListener";
private static final boolean DBG = false;
private Context mContext;
private HashMap<Handler, Integer> mHandlers = new HashMap<Handler, Integer>();
private State mState;
private boolean mListening;
private String mReason;
private boolean mIsFailover;
private NetworkInfo mNetworkInfo;
private NetworkInfo mOtherNetworkInfo;
private ConnectivityBroadcastReceiver mReceiver;
private class ConnectivityBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION) ||
mListening == false) {
Log.w(TAG, "onReceived() called with " + mState.toString() + " and " + intent);
return;
}
boolean noConnectivity =
intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
if (noConnectivity) {
mState = State.NOT_CONNECTED;
} else {
mState = State.CONNECTED;
}
mNetworkInfo = (NetworkInfo)
intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
mOtherNetworkInfo = (NetworkInfo)
intent.getParcelableExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO);
mReason = intent.getStringExtra(ConnectivityManager.EXTRA_REASON);
mIsFailover =
intent.getBooleanExtra(ConnectivityManager.EXTRA_IS_FAILOVER, false);
if (DBG) {
Log.d(TAG, "onReceive(): mNetworkInfo=" + mNetworkInfo + " mOtherNetworkInfo = "
+ (mOtherNetworkInfo == null ? "[none]" : mOtherNetworkInfo +
" noConn=" + noConnectivity) + " mState=" + mState.toString());
}
// Notifiy any handlers.
Iterator<Handler> it = mHandlers.keySet().iterator();
while (it.hasNext()) {
Handler target = it.next();
Message message = Message.obtain(target, mHandlers.get(target));
target.sendMessage(message);
}
}
};
public enum State {
UNKNOWN,
/** This state is returned if there is connectivity to any network **/
CONNECTED,
ONNECTED
}
public NetworkConnectivityListener() {
mState = State.UNKNOWN;
mReceiver = new ConnectivityBroadcastReceiver();
}
/**
* This method starts listening for network connectivity state changes.
* #param context
*/
public synchronized void startListening(Context context) {
if (!mListening) {
mContext = context;
IntentFilter filter = new IntentFilter();
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
context.registerReceiver(mReceiver, filter);
mListening = true;
}
}
/**
* This method stops this class from listening for network changes.
*/
public synchronized void stopListening() {
if (mListening) {
mContext.unregisterReceiver(mReceiver);
mContext = null;
mNetworkInfo = null;
mOtherNetworkInfo = null;
mIsFailover = false;
mReason = null;
mListening = false;
}
}
public void registerHandler(Handler target, int what) {
mHandlers.put(target, what);
}
/**
* This methods unregisters the specified Handler.
* #param target
*/
public void unregisterHandler(Handler target) {
mHandlers.remove(target);
}
public State getState() {
return mState;
}
public NetworkInfo getNetworkInfo() {
return mNetworkInfo;
}
public NetworkInfo getOtherNetworkInfo() {
return mOtherNetworkInfo;
}
public boolean isFailover() {
return mIsFailover;
}
public String getReason() {
return mReason;
}
}
I took this code register a reciever for checking the internet connection Availability.And i use the following line to put it on the Manifiest file .But when try this code i get following error.I used this code to schaeck the internet connection before i send some data.I donot know how to register this on manifest file
02-13 16:59:31.109: E/AndroidRuntime(28123): java.lang.RuntimeException: Unable to instantiate receiver org.apache.cordova.example.NetworkConnectivityListener: java.lang.ClassCastException: org.apache.cordova.example.NetworkConnectivityListener cannot be cast to android.content.BroadcastReceiver
Because NetworkConnectivityListener is not a child of BroadcastReceiver that's why the error pop's up
SOLUTION:
In Manifest file Register the listener as follows,
<receiver android:name="org.apache.cordova.example.NetworkConnectivityListener$ConnectivityBroadcastReceiver" />
ALTERNATE:
Register the Receiver within the NetworkConnectivityListener itself as you did and remove the entry in Manifest.
extend NetworkConnectivityListener from BroadcastReceiver, you're trying to register regular class instead BroadcastReceiver class
public class FBPost extends Service{
private Bundle params = new Bundle();
private String userID="";
String response;
public void onCreate(String userID,String name)
{
super.onCreate();
params.putString("message", "Test " + new Date().toLocaleString() );
params.putString("caption", "Hey there");
this.userID=userID;
}
#Override
public int onStartCommand( Intent intent , int flags , int startId )
{
if(checkInternetConnection())
{
fb_post();
return 0;
}
else
{
BroadcastReceiver connec_recv= new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(checkInternetConnection())
fb_post();
}
};
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(connec_recv, intentFilter);
}
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
private boolean checkInternetConnection() {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
// test for connection
if (cm.getActiveNetworkInfo() != null
&& cm.getActiveNetworkInfo().isAvailable()
&& cm.getActiveNetworkInfo().isConnected()) {
try{
URL url = new URL("http://www.google.com");
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
in.close();
return true;
} catch (Exception e) {
return false;
}
}
return false;
}
private void fb_post()
{
//MORE CODE
}
}
what if there's still no internet conectivity? Should i just call another instance of the same service from the broadcast receiver instead of fb_post()? Can I make a service wait() and then notify() every time a connectivity broadcast receiver recieves a connection change broadcast?
In my opinion the right way to implement this kind of functionality is as follows:
If there is no connection - give up the Service, register a BroadcastReceiver to listen for connection changes and save a flag somewhere (SharedPreferences for example) telling that there is work left to do
When the connection is established and your flag is true - start the Service again and do the job
Hope this helps.