My app has a repeating alarm with a number picker, so if i chose to repeat every one minute a sound goes off every one minute, but if the user received a phone call the alarm doesn't stop. How can i solve this problem? What should i implement in the receiver activity in order for it to detect a phone call?
Receiver:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.media.MediaPlayer;
public class MainReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
MediaPlayer m=MediaPlayer.create(context, R.raw.sound2);
m.start();
}
}
Just updated my above answer a bit:As per Android documentation for AlarmManager.setRepeating (int type, long triggerAtMillis, long intervalMillis, PendingIntent operation), it will continue to come until explicitly removed with cancel(PendingIntent). If you are using this API then either you have to cancel it on call or in your receiver you have to add call condition and just return without doing anything.
try code:
final MediaPlayer m = MediaPlayer.create(context, R.raw.sound2);
m.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
m.start();
}
});
AudioManager am = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
am.requestAudioFocus(new AudioManager.OnAudioFocusChangeListener() {
#Override
public void onAudioFocusChange(int focusChange) {
Log.i("FOCUS",focusChange + "");
if (focusChange > 0)
m.start();
else
m.pause();
}
}, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
Or make your BroadcastReceiver receiver phone incoming state:
public class MainReceiver extends BroadcastReceiver {
private static final String PLAYAUDIO = "PLAYAUDIO";
private static final String PHONE_STATE = "android.intent.action.PHONE_STATE";
private static MediaPlayer m;
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(PLAYAUDIO)) {
m= MediaPlayer.create(context, R.raw.sound2);
m.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
m.start();
}
});
m.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
m = null;
}
});
} else
if (intent.getAction().equals(PHONE_STATE)) {// NEW CALL STATE
String extra = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
if (extra.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_IDLE)
&& m != null)
m.start();
else if (m != null)
m.pause();
}
}
}
AndroidManifest.xml like this:
<receiver android:name="YourPackage.MainReceiver">
<intent-filter>
<action android:name="PLAYAUDIO"/>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
//Add permistion
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
Guys i finally figured it out, i saw couple of examples of telephonymanager and i wrote this one out and worked fine.
public class MainReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
MediaPlayer m=MediaPlayer.create(context, R.raw.sound2);
TelephonyManager tm =
(TelephonyManager)context.getSystemService(Service.TELEPHONY_SERVICE);
switch (tm.getCallState()) {
case TelephonyManager.CALL_STATE_RINGING:
m.stop();
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
m.stop();
break;
case TelephonyManager.CALL_STATE_IDLE:
m.start();
break;
}
}
}
Related
I am looking for a way to check and to listen to my internet connection but since the latest Android version doesn't support registering a broadcast in Manifest, I am looking for a way to implement something that works on all the Android versions. So far I couldn't find any solutions.
I tried adding a Broadcast intent filter into my Manifest file but that's not allowed in the more recent Android versions.
<receiver
android:name="utilities.NetworkStateChangeReceiver"
android:exported="true"
android:enabled="true"
android:label="NetworkConnection" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<action android:name="android.net.wifi.STATE_CHANGE"/>
</intent-filter>
</receiver>
public class NetworkStateChangeReceiver extends BroadcastReceiver {
public static final String NETWORK_AVAILABLE_ACTION = "NetworkAvailable";
public static final String IS_NETWORK_AVAILABLE = "isNetworkAvailable";
#Override
public void onReceive(Context context, Intent intent) {
Intent networkStateIntent = new Intent(NETWORK_AVAILABLE_ACTION);
networkStateIntent.putExtra(IS_NETWORK_AVAILABLE, isConnectedToInternet(context));
LocalBroadcastManager.getInstance(context).sendBroadcast(networkStateIntent);
}
private boolean isConnectedToInternet(Context context) {
final ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
boolean isMobile = false, isWifi = false;
NetworkInfo[] infoAvailableNetworks = cm.getAllNetworkInfo();
if (infoAvailableNetworks != null) {
for (NetworkInfo network : infoAvailableNetworks) {
if (network.getType() == ConnectivityManager.TYPE_WIFI) {
if (network.isConnected() && network.isAvailable())
isWifi = true;
}
if (network.getType() == ConnectivityManager.TYPE_MOBILE) {
if (network.isConnected() && network.isAvailable())
isMobile = true;
}
}
}
return isMobile || isWifi;
}
}
My receiver is not able to receive a broadcast
I'm using pretty much the same logic with IntentFilter and it works for me pretty good without registering it in the Manifest file.
Interface:
public interface IReceiverStateChange {
void register(BroadcastReceiver broadcastReceiver);
void unregister(BroadcastReceiver broadcastReceiver);
}
Implementation:
public class NetworkReceiverStateChange implements IReceiverStateChange {
private Context mContext;
private Boolean mIsRegistered = false;
public NetworkReceiverStateChange(Context context) {
mContext = context;
}
#Override
public void register(BroadcastReceiver broadcastReceiver) {
if (!mIsRegistered) {
IntentFilter netWorkIntentFilter = new
IntentFilter("android.net.conn.CONNECTIVITY_CHANGE");
mContext.registerReceiver(broadcastReceiver, netWorkIntentFilter);
mIsRegistered = true;
}
}
#Override
public void unregister(BroadcastReceiver broadcastReceiver) {
if (mIsRegistered) {
mContext.unregisterReceiver(broadcastReceiver);
mIsRegistered = false;
}
}
}
Register in the desired activity:
if (mNetworkStateChange == null) {
mNetworkStateChange = new NetworkReceiverStateChange(this);
}
mNetworkStateChange.register(mNetworkBroadcastReceiver);
Unregister in onDestroy:
if (mNetworkStateChange != null) {
mNetworkStateChange.unregister(mNetworkBroadcastReceiver);
}
The BroadcastReceiver Obj:
//The CONNECTIVITY_ACTION broadcast seems to be sticky on some devices (even
though the documentation implies that it is not).
// This means that when you register the receiver it will immediately call
onReceive() with the most recently sent broadcast.
private final BroadcastReceiver mNetworkBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action != null && action.matches("android.net.conn.CONNECTIVITY_CHANGE")) {
<DO SOMETHING>
}
}
};
Hope it helps :)
If you want to check your internet connection all of your activities you can follow below code :-
NetworkSchedulerService.java
public class NetworkSchedulerService extends JobService implements
ConnectivityReceiver.ConnectivityReceiverListener {
private static final String TAG = NetworkSchedulerService.class.getSimpleName();
private ConnectivityReceiver mConnectivityReceiver;
#Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "Service created");
prefManager = PrefManager.getInstance(this);
mConnectivityReceiver = new ConnectivityReceiver(this);
}
/**
* When the app's NetworkConnectionActivity is created, it starts this service. This is so that the
* activity and this service can communicate back and forth. See "setUiCallback()"
*/
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand");
return START_NOT_STICKY;
}
#Override
public boolean onStartJob(JobParameters params) {
Log.i(TAG, "onStartJob" + mConnectivityReceiver);
registerReceiver(mConnectivityReceiver, new IntentFilter(CONNECTIVITY_ACTION));
return true;
}
#Override
public boolean onStopJob(JobParameters params) {
Log.i(TAG, "onStopJob");
unregisterReceiver(mConnectivityReceiver);
return true;
}
#Override
public void onNetworkConnectionChanged(boolean isConnected) {
if(isConnected){
Toast.makeText(this,"connected to internet",Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this,"no internet connection",Toast.LENGTH_SHORT).show();
}
}
}
In manifest file
<service
android:name=".NetworkSchedulerService"
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE"/>```
create a Application class
class MyApplication extends Application {
override fun onCreate() {
super.onCreate()
scheduleJob()
}
override fun onStop() {
super.onStop()
// A service can be "started" and/or "bound". In this case, it's "started" by this Activity
// and "bound" to the JobScheduler (also called "Scheduled" by the JobScheduler). This call
// to stopService() won't prevent scheduled jobs to be processed. However, failing
// to call stopService() would keep it alive indefinitely.
stopService(Intent(this, NetworkSchedulerService::class.java))
}
override fun onStart(){
val startServiceIntent = Intent(this, NetworkSchedulerService::class.java)
startService(startServiceIntent)
}
private fun scheduleJob() {
val myJob = JobInfo.Builder(0, ComponentName(this, NetworkSchedulerService::class.java))
.setRequiresCharging(true)
.setMinimumLatency(1000)
.setOverrideDeadline(2000)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.setPersisted(true)
.build()
val jobScheduler = getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
jobScheduler.schedule(myJob)
}
}
define application class in manifest file
BroadcastReceiver class ->
public class ConnectivityReceiver extends BroadcastReceiver {
private ConnectivityReceiverListener mConnectivityReceiverListener;
ConnectivityReceiver(ConnectivityReceiverListener listener) {
mConnectivityReceiverListener = listener;
}
#Override
public void onReceive(Context context, Intent intent) {
mConnectivityReceiverListener.onNetworkConnectionChanged(isConnected(context));
}
public static boolean isConnected(Context context) {
ConnectivityManager cm = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
}
public interface ConnectivityReceiverListener {
void onNetworkConnectionChanged(boolean isConnected);
}
}
**onNetworkConnectionChanged will notify when internet is connected or not (NetworkSchedulerService.java)
Don't define BroadCastReceiver in manifest file. make sure to provide internect permission , CHANGE_NETWORK_STATE,ACCESS_NETWORK_STATE
**
I hope this will help you. Let me know if there is any problem. Happy Coding :-)
I am a newbie in Android Developer
I am building a game app on Android Studio. But, I have had a problem about Background music while playing game. I have used Bound Service to handle through the class: MusicService extends Service implements MediaPlayer.OnErrorListener. But, my App was stopped when I run.
I have tried to fixed and explored solutions, but, I can't run app...
This is source code:
MusicService.java
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnErrorListener;
import android.os.Binder;
import android.os.IBinder;
import android.widget.Toast;
public class MusicService extends Service implements MediaPlayer.OnErrorListener {
private final IBinder mBinder = new ServiceBinder();
MediaPlayer mPlayer;
private int length = 0;
public MediaPlayer Player;
public MusicService() {
}
public class ServiceBinder extends Binder {
public MusicService getService() {
return MusicService.this;
}
}
#Override
public IBinder onBind(Intent arg0) {
return mBinder;
}
#Override
public void onCreate() {
super.onCreate();
Player = MediaPlayer.create(this, R.raw.one);
mPlayer.setOnErrorListener(this);
if (mPlayer != null) {
mPlayer.setLooping(true);
mPlayer.setVolume(100, 100);
}
mPlayer.setOnErrorListener(new OnErrorListener() {
public boolean onError(MediaPlayer mp, int what, int
extra) {
onError(mPlayer, what, extra);
return true;
}
});
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mPlayer.start();
return START_STICKY;
}
public void pauseMusic() {
if (mPlayer.isPlaying()) {
mPlayer.pause();
length = mPlayer.getCurrentPosition();
}
}
public void resumeMusic() {
if (mPlayer.isPlaying() == false) {
mPlayer.seekTo(length);
mPlayer.start();
}
}
public void stopMusic() {
mPlayer.stop();
mPlayer.release();
mPlayer = null;
}
#Override
public void onDestroy() {
super.onDestroy();
if (mPlayer != null) {
try {
mPlayer.stop();
mPlayer.release();
} finally {
mPlayer = null;
}
}
}
public boolean onError(MediaPlayer mp, int what, int extra) {
Toast.makeText(this, "music player failed", Toast.LENGTH_SHORT).show();
if (mPlayer != null) {
try {
mPlayer.stop();
mPlayer.release();
} finally {
mPlayer = null;
}
}
return false;
}
}
and, MainActivity.java
public class MainActivity extends AppCompatActivity {
private boolean mIsBound = false;
private MusicService mServ;
private ServiceConnection Scon =new ServiceConnection(){
public void onServiceConnected(ComponentName name, IBinder service) {
MusicService.ServiceBinder binder = (MusicService.ServiceBinder)service;
mServ =binder.getService();
}
public void onServiceDisconnected(ComponentName name) {
mServ = null;
}
};
// Activity create UI its
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
// Activity start.
#Override
protected void onStart() {
super.onStart();
// create Intent for MusicService.
Intent intent = new Intent(MainActivity.this,MusicService.class);
// call method bindService(..) to bind activity
this.bindService(intent, Scon, Context.BIND_AUTO_CREATE);
}
//Activity stop
#Override
protected void onStop() {
super.onStop();
if (mIsBound) {
this.unbindService(Scon);
mIsBound = false;
}
}
Then, I didn't also forget add the code following in AndroidManifest
<service
android:name=".MusicService"
android:enabled="true"
android:exported="true"></service>
That's all problems mine. This makes me so confuse
Help you, please
Thank you very much
Can you add more log debug in logcat? Not sure but I guess problem is you call:
mPlayer.start();
in onStartComand(). Your service should implement MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener,MediaPlayer.OnCompletionListener and above function should be call in
void onPrepared(MediaPlayer mp)
My App goes like this:
When you first start the app, you'll see a button. Connecting or disconnecting the AC charger doesn't affect anything until you hit that Start button.
When you tap the Start button, the "service" is started.
Now if you remove the AC charger you will hear an alarm sound.
Connecting the AC with the device again should stop the alarm but it does NOT.
Now removing the AC again starts another alarm. The alarms overlap.
Can you help me find the bug?
Thanks
My work so far:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.yousef.mustafa.antitheft">
<application
android:allowBackup="true"
android:icon="#mipmap/antitheft"
android:label="#string/app_name"
android:roundIcon="#mipmap/antitheft"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".PowerConnectionReceiver">
</receiver>
</application>
</manifest>
MainActivity.java
public class MainActivity extends AppCompatActivity {
Button startServiceButton;
PowerConnectionReceiver powerConnectionReceiver;
BroadcastReceiver powerDisconnectedBroadcastReceiver;
BroadcastReceiver powerConnectedBroadcastReceiver;
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
powerConnectionReceiver = new PowerConnectionReceiver(true);
startServiceButton = (ToggleButton) findViewById(R.id.startServiceButton);
powerDisconnectedBroadcastReceiver = new PowerConnectionReceiver(true);
powerConnectedBroadcastReceiver = new PowerConnectionReceiver(false);
startServiceButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (startServiceButton.isActivated()) {
unregisterReceiver(powerDisconnectedBroadcastReceiver);
unregisterReceiver(powerConnectedBroadcastReceiver);
Toast.makeText(MainActivity.this, "Service stopped", Toast.LENGTH_SHORT).show();
startServiceButton.setActivated(false);
} else {
monitorBatteryChanges();
}
}
});
}
private void monitorBatteryChanges() {
IntentFilter powerDisconnectedIntentFilter = new IntentFilter("android.intent.action.ACTION_POWER_DISCONNECTED");
registerReceiver(powerDisconnectedBroadcastReceiver, powerDisconnectedIntentFilter);
IntentFilter powerConnectedIntentFilter = new IntentFilter("android.intent.action.ACTION_POWER_CONNECTED");
registerReceiver(powerConnectedBroadcastReceiver, powerConnectedIntentFilter);
Toast.makeText(MainActivity.this, "Service started", Toast.LENGTH_SHORT).show();
startServiceButton.setActivated(true);
}
}
PowerConnectionReceiver.java
public class PowerConnectionReceiver extends BroadcastReceiver {
MediaPlayer mediaPlayer = new MediaPlayer();
// Determine whether the AC is disconnected or not
private boolean POWER_DISCONNECTED = true;
PowerConnectionReceiver(boolean disconnected) {
this.POWER_DISCONNECTED = disconnected;
}
#Override
public void onReceive(Context context, Intent intent) {
if (POWER_DISCONNECTED) {
mediaPlayer = MediaPlayer.create(context, R.raw.alarm_2);
Toast.makeText(context, "Alarm started", Toast.LENGTH_SHORT).show();
mediaPlayer.start();
mediaPlayer.setLooping(true);
//POWER_DISCONNECTED = false;
} else {
try {
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.release();
Toast.makeText(context, "Alarm stopped", Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
The bug is in your complex code.
You register two different instances of PowerConnectionReceiver one for "connected" and another for "disconnected" events. So MediaPlayer is started in "connected" receiver, and you try to stop MediaPlayer in "disconected", but it doesn't play.
You should remove POWER_DISCONNECTED field, and handle event in a single instance of receiver. You can register a single receiver for multiple events and use intent.getAction() to check how to handle it.
UPD
Also you can make your receiver singleton, to prevent multiple registrations, and playing of multiple MediaPlayers
I was finally able to find a solution.
MainActivity.java
public class MainActivity extends AppCompatActivity {
Button startServiceButton;
BroadcastReceiver powerConnectionBroadcastReceiver;
IntentFilter powerDisconnectedIntentFilter = new IntentFilter("android.intent.action.ACTION_POWER_DISCONNECTED");
IntentFilter powerConnectedIntentFilter = new IntentFilter("android.intent.action.ACTION_POWER_CONNECTED");
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startServiceButton = (ToggleButton) findViewById(R.id.startServiceButton);
powerConnectionBroadcastReceiver = new PowerConnectionBroadcastReceiver();
startServiceButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (startServiceButton.isActivated()) {
unregisterReceiver(powerConnectionBroadcastReceiver);
startServiceButton.setActivated(false);
Toast.makeText(MainActivity.this, "Service stopped", Toast.LENGTH_SHORT).show();
} else {
monitorBatteryChanges();
}
}
});
}
private void monitorBatteryChanges() {
registerReceiver(powerConnectionBroadcastReceiver, powerDisconnectedIntentFilter);
registerReceiver(powerConnectionBroadcastReceiver, powerConnectedIntentFilter);
startServiceButton.setActivated(true);
Toast.makeText(MainActivity.this, "Service started", Toast.LENGTH_SHORT).show();
}
}
PowerConnectionBroadcastReceiver.java
public class PowerConnectionBroadcastReceiver extends BroadcastReceiver {
MediaPlayer mediaPlayer;
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_POWER_DISCONNECTED)) {
mediaPlayer = MediaPlayer.create(context, R.raw.alarm_1);
mediaPlayer.start();
mediaPlayer.setLooping(true);
Toast.makeText(context, "Alarm started", Toast.LENGTH_SHORT).show();
} else {
try {
if (mediaPlayer != null)
mediaPlayer.release();
Toast.makeText(context, "Alarm stopped", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
It may not be the best solution but it works :)
Thanks for the help.
I am trying to update the UI according to change of a variable in BroadcastReceiver. Thus, I need to call a method (to get the variable I mentioned) of a class which extends BroadcastReceiver in MainActivity depending on but I cannot get the true return value in any way.
The class which extends BroadcastReceiver is this:
public class ProviderChangeReceiver extends BroadcastReceiver {
private static boolean isProviderActive;
#Override
public void onReceive(Context context, Intent intent) {
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER) && lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
Log.v("-> ", "GPS + NETWORK");
isProviderActive = true;
}
else if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER) && !lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
Log.v("-> ", "GPS");
isProviderActive = true;
}
else if (lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER) && !lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
Log.v("-> ", "NETWORK");
isProviderActive = true;
}
else
{
Log.v("-> ", "DISCONNECT");
isProviderActive = false;
}
}
public static boolean isProviderActive(){
return isProviderActive;
}
}
I need to get true value of isProviderActive to use in this part of MainActivity:
...
private class ProviderChangeReceiver_updateUI extends ProviderChangeReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
MapsActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Log.v("-A", ""+ isProviderActive());
if (isProviderActive())
originButton.setVisibility(View.VISIBLE);
else
originButton.setVisibility(View.INVISIBLE);
}
});
}
}
I know that indicating isProviderActive as static is not a good approach but I just want to observe its changes. As you guess, I got nonsensical return values all the time. To values of boolean isProviderActive without problem, what do you advise?
Edit: My temporary solution to update UI according to changes in BroadcastReceiver.
Forget about creating a separate class for ProviderChangeReceiver. Instead of the code segment above, following segment should be added in MainActivity. Also, it goes without saying that there is the initialization of ProviderChangeReceiver in onCreate().
...
private class ProviderChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
MapsActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Log.v("COUNT: ", "" + count++);
if (isLocationProviderActive()) {
originButton.getBackground().setAlpha(220);
originButton.setEnabled(true);
//marker.setVisible(true);
}
else {
originButton.getBackground().setAlpha(77);
originButton.setEnabled(false);
marker.setVisible(false);
}
}
});
}
}
private boolean isLocationProviderActive(){
if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER) && lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER))
return true;
return false;
}
Of course then register the receiver in onCreate() as well:
registerReceiver(pcr, new IntentFilter("android.location.PROVIDERS_CHANGED"));
The reason that every time isProvidrActive changed the whole activity got regenerated is because I sent the intent using context.startActivity(i) but rather this time we send the intent using contect.sendBroadcast(i) to the ProviderChangeReceiver_updateUI inner class which update only desired part of the UI. So below is the new code.
private static boolean isProviderActive;
#Override
public void onReceive(Context context, Intent intent) {
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER) && lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
Log.v("-> ", "GPS + NETWORK");
isProviderActive = true;
}
else if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER) && !lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
Log.v("-> ", "GPS");
isProviderActive = true;
}
else if (lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER) && !lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
Log.v("-> ", "NETWORK");
isProviderActive = true;
}
else
{
Log.v("-> ", "DISCONNECT");
isProviderActive = false;
}
//Send value of isProviderActive to ProviderChangeReceiver_updateUI
Intent i = new Intent(context, ProviderChangeReceiver_updateUI.class);
i.putExtra("isProvidrActv", isProviderActive);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.sendBroadcast(i);
}
Edit your manifest file to enable the inner class ProviderChangeReceiver_updateUI to listen for broadcast sent by our broadcastReciever, add the following entry to manifest
<receiver android:name="<package-name>.MainActivity$ProviderChangeReceiver_updateUI"
android:enabled="true" >
<intent-filter>
</intent-filter>
</receiver>
the $ sign indicates inner class. No need to add intent-filters unless required.
And in your ProviderChangeReceiver_updateUI class in the onReceive() method get the value of isProviderActive
...
//changed the identifiers from private to public static and the class extends //BroadcastReceiver
public static class ProviderChangeReceiver_updateUI extends BroadcastReceiver {
//Empty constructor to prevent exception can't instantiate no empty constructor
public ProviderChangeReceiver_updateUI(){
}
//Removed the final keyword from handler
private Handler handler; // Handler used to execute code on the UI thread
public ProviderChangeReceiver_updateUI(Handler handler) {
this.handler = handler;
}
#Override
public void onReceive(final Context context, final Intent intent) {
boolean isProvidrActv = intent.getBooleanExtra("isProvidrActv", false);
//mapsActivity is a global static object of the class MapsActivity<br/>
//instantiate it the onCreate() method of mainactivity for ex:<br/>
/*public class MapsActivity extends Activity{<br/>
static MapsActivity mapsActivity;
#Override
protected void onCreate(Bundle savedInstancestate){
ma = new MapsActivity();
}*/
mapsActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
if (isProvidrActv)
originButton.setVisibility(View.VISIBLE);
else
originButton.setVisibility(View.INVISIBLE);
}
});
}
}
I think a nice way to handle something like this is with an eventbus.
Take a look at Squares Otto library.
In your broadcast receiver you would publish the change event and then in your activity you would subscribe to the event and update the ui.
Based on the context of your question, I think you would be able to avoid the broadcast receiver entirely, since I suspect you have something watching your provider and then broadcasting the event.
Update: (based on comments)
I think the way this would work would be something like this
In the code that detects the change in location provider:
if (bothProvidersAreStopped()) {
bus.publish(new BothProvidersStoppedEvent());
} else if (onlyNetworkProviderIsStopped() {
bus.publish(new NetworkProviderStoppedEvent());
} else if (onlyGpsProviderIsStopped() {
bus.publish(new GpsProviderStoppedEvent());
}
in your activity
#Subscribe public void onBothProvidersStopped(BothProvidersStopped event) {
// handle case were both providers just stopped
}
#Subscribe public void onNetworkProvidersStopped(BothProvidersStopped event) {
// handle case were network provider just stopped
}
#Subscribe public void onGpsProvidersStopped(BothProvidersStopped event) {
// handle case were gps provider just stopped
}
I discovered this battery widget in github https://github.com/onlinux/AndroidBatteryWidget. I want create the same graph that there is in the application. The problem is that this is a widget and the things are a little bit differents. The widget has a class https://github.com/onlinux/AndroidBatteryWidget/blob/master/src/fr/free/onlinux/AndroidBatteryWidget/AndroidBatteryWidgetProvider.java with a service UpdateService class. Thinking i don't need the widget provider, i take only the service and i created a new class called UpdateService.java like this:
package com.mypackage.app;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
import android.os.IBinder;
import android.util.Log;
import android.widget.RemoteViews;
import android.app.PendingIntent;
import android.app.Service;
public static class UpdateService extends Service {
public final static String TAG = "Bat";
//private static final String TAG = AndroidBatteryWidgetProvider.class.getSimpleName();
public static Boolean debug = true;
BatteryInfo mBI = null;
public void updateWidget(Context context, Intent batteryIntent){
if (debug) Log.i(TAG,"---------- updateWidget");
SimpleDateFormat formatter = new SimpleDateFormat(" HH:mm:ss ");
RemoteViews updateViews = new RemoteViews(context.getPackageName(), R.layout.androidbatterywidget_layout);
updateViews.setTextViewText(R.id.level, "waiting!");
final int status = batteryIntent.getIntExtra("status", BatteryManager.BATTERY_STATUS_UNKNOWN);
final int plugged = batteryIntent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
final int level = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
updateViews.setTextViewText(R.id.level, "" + level + " %" );
updateViews.setTextViewText(R.id.time, formatter.format(new Date()));
final int temperature = batteryIntent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, -1);
String tempString= String.format("%.0f°C", new Float(temperature/10));
if (debug) Log.d(TAG,"BAT:" + tempString + " " + level + "%");
updateViews.setTextViewText(R.id.temperature, tempString );
final int voltage = batteryIntent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, -1);
Intent i = new Intent(context, AndroidBatteryActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
/* updateViews.setTextViewText(R.id.voltage, "" + voltage + " mV" );
updateViews.setOnClickPendingIntent(R.id.layout ,
PendingIntent.getActivity(context, 0,
new Intent(context, AndroidBatteryActivity.class),Intent.FLAG_ACTIVITY_NEW_TASK));
ComponentName myComponentName = new ComponentName(context, AndroidBatteryWidgetProvider.class);
AppWidgetManager manager = AppWidgetManager.getInstance(context);
manager.updateAppWidget(myComponentName, updateViews); */
//Second, update database in a thread
new Thread (new Runnable(){
public void run(){
final Context c=getApplicationContext();
DBHelper db = new DBHelper(c);
db.record( level, status, plugged );
db.deleteOldEntries();
db.close();
if (debug) Log.i( TAG, "---------- Add record: " + level + " time: "+ Calendar.getInstance().getTimeInMillis() );
}
}).start();
}
public void handleCommand(Intent intent){
if(mBI == null)
{
mBI = new BatteryInfo(this);
// IntentFilter mIntentFilter = new IntentFilter();
// mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
// registerReceiver(mBI, mIntentFilter);
// After registering mBI, another update is immediately processed.
// So, skip double update processing.
return;
}
//update widget views and database
updateWidget(getApplicationContext(), intent);
}
#Override
public void onStart(Intent intent, int startId) {
handleCommand(intent);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (debug)
Log.d(TAG, "----------------- onStartCommand");
handleCommand(intent);
// The service has to be running otherwise the broadcast ACTION_BATTERY_CHANGED wont be received anymore
// thats why it returns START_STICKY
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
try{
if(mBI != null) {
if (debug)
Log.d(TAG, "----------------- onDestroy: unregisterReceiver(mBI)" );
unregisterReceiver(mBI);
}
}catch(Exception e)
{Log.e(TAG, "", e);}
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
}
}
and in my MainActivity i created a button if clicked go to graph, so onclick
Intent intent = new Intent(context, UpdateService.class);
context.startService(intent);
Now, what happen is that i can see from the logCat the receiver and the service goes well. But clicking the button in the application nothing happen. The app exit and none activity starts. In the Manifest i wrote
<service android:name=".UpdateService" />
<receiver android:name=".BatteryInfo" android:label="BatteryInfo">
<intent-filter>
<action android:name="android.intent.action.BATTERY_CHANGED" />
</intent-filter>
</receiver>
<activity
android:name=".AndroidBatteryActivity"
android:label="#string/app_name" >
</activity>
<activity android:name="org.achartengine.GraphicalActivity" >
</activity>
EDIT: I try to edit a little bit the code and now aadding this part
Intent i = new Intent(context, AndroidBatteryActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
Start the Activity AndroidBatteryActivity but is all black and nothing appear. If The AndroidBatteryActivity is this one:
public class AndroidBatteryActivity extends Activity {
public Intent intent ;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
intent = new BatteryChart().execute(this);
startActivity(intent);
finish();
}
public void myfinish(){
Log.i("AndroidBatteryActivity", "finish");
finish();
}
}
and BatteryChart is the class with graph with achartengine.
. How can i adapt the code in mine? How can i start the graph? What i have to change? Thanks
Its possible that you may have figured out the answer by now, but anyways here is how to do it :
public class MyBatteryReceiver extends Service {
private int batterylevel = 0;
private String batteryStatus = "";
public final static String TAG = "Bat";
public static Boolean debug = true;
private BroadcastReceiver myReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
batterylevel = intent.getIntExtra("level", 0);
final int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
final int status = intent.getIntExtra("status",
BatteryManager.BATTERY_STATUS_UNKNOWN);
String strStatus;
if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
batteryStatus = "Charging";
} else if (status == BatteryManager.BATTERY_STATUS_DISCHARGING) {
batteryStatus = "Discharging";
} else if (status == BatteryManager.BATTERY_STATUS_NOT_CHARGING) {
batteryStatus = "Not charging";
} else if (status == BatteryManager.BATTERY_STATUS_FULL) {
batteryStatus = "Full";
} else {
batteryStatus = "";
}
new Thread (new Runnable(){
public void run(){
final Context c=getApplicationContext();
DBHelper db = new DBHelper(c);
db.record( batterylevel, status, plugged );
db.deleteOldEntries();
db.close();
if (debug) Log.i( TAG, "---------- Add record: " + batterylevel + " time: "+ Calendar.getInstance().getTimeInMillis() );
}
}).start();
}
}
};
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(myReceiver, intentFilter);
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
unregisterReceiver(myReceiver);
}
}
This is your Activity
public class AndroidBatteryActivity extends Activity {
public Intent intent ;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_battery_chart);
intent = new BatteryChart().execute(this);
startActivity(intent);
finish();
}
public void myfinish(){
Log.i("AndroidBatteryActivity", "finish");
finish();
}
}
You need to Start the service from where you prefer
Intent intent = new
Intent(YourActivity.this,yourpackagename.MyBatteryReceiver.class);
YourActivity.this.startService(intent);
And this tag in Manifest
<service
android:name="yourpackagename.MyBatteryReceiver"
android:label="MyBatteryReceiver" >
<intent-filter>
<action android:name="android.intent.action.BATTERY_CHANGED" />
</intent-filter>
</service>
Just change the class name from MyBatteryReceiver to UpdateService for your code