I am trying to use a BroadcastReceiver as an inner class to track the network state but I got the exception in the title. What should I do to fix this problem?
public class NetworkChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
final ConnectivityManager connMgr = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
final android.net.NetworkInfo wifi = connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
final android.net.NetworkInfo mobile = connMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
if (wifi.isAvailable() || mobile.isAvailable()) {
setupData();
Log.d("Netowk Available ", "Flag No 1");
}
}
}
Your
inner Broadcast receiver must be static ( to be registered through Manifest)
OR
Non-static broadcast receiver must be registered and unregistered inside the Parent class
for this.
I was using an Inner broadcast reciver, without registering it within the class. Either make it static and register in Manifest , or Make it non static and register and unregister inside the parent class .
A non-static inner class cannot be registered via the AndroidManifest.xml. You can either:
Register it dynamically as outlined in this thread, and remove the empty constructor.
Or,
Make your inner class static, and register it in the AndroidManifext.xml.
just make your Receiver Class static like:
public [static] class ReceiverClass extends BroadcastReceiver
e~~I just meet that problem,and I refactor the class NetworkChangeReceiver to an another place
Related
Pass additional parameters to a dynamically registered BroadcastReceiver.
The problem is basic: I want to pass parameters to a BroadcastReceiver. Can this be done? Even when the receiver is created dynamically?
Additionally, say I create an anonymous BroadcastReceiver i.e. as a variable implementation. Can I reference the encapsulating class variables? Check the code below for how I stop / start the file observer.
// Create the external media broadcast receiver.
mExternalMediaBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(final Context context, final Intent intent) {
// if action = media removed, stop the file observer.
EncapsulatingFragment.this.mFileObserver.stopWatching()
}
};
Is this valid?
Is this valid?
So long as the receiver has the same lifetime as EncapsulatingFragment.this, probably.
I want to pass parameters to a BroadcastReceiver. Can this be done? Even when the receiver is created dynamically?
Create an actual class and pass in the values to the constructor:
class WhateverReceiver extends BroadcastReceiver {
FileObserver mFileObserver;
WhateverReceiver(FileObserver observer) {
mFileObserver = observer;
}
#Override
public void onReceive(final Context context, final Intent intent) {
// if action = media removed, stop the file observer.
mFileObserver.stopWatching();
}
}
Then, in your fragment:
mExternalMediaBroadcastReceiver = new WhateverReceiver(mFileObserver);
All that being said... you might want to consider whether this logic should be implemented in your fragment. I/O-related stuff ideally lies outside of a fragment, such as in a repository object.
I know this is a broad question, but this might be any average android developer's question. In a BroadcastReceiver, what is the context parameter passed through onReceive() method?
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
}
}
I just know we have 3 main types of context: Activity, Service, Application.
Initially Context represents environment data and it is used to create application specific resource.
for example, if you create a new object for a class with "this" keyword as its context, that object was resource for that specific class and not for others.
context was also used to share system resources like layoutInflater, NotificationManager and so on.
In Broadcast receiver, context refers to the activity or class in which the broadcast receiver is running. if your "MainActivity" sends a broadcast then the context would have something like the following "com.example.MainActivity"
I am creating a intent service,and inside this intent service I am creating new class like this:
public class ConnectionIntent extends IntentService {
final Connection connection=new Connection();
public ConnectionIntent() {
super("ConnectionIntent");
}
...
I am calling this service for multiple times.How can I create new Connection() class for once ? I mean if this service is calling for first create a new Connection() class if this service calling for secondly don't create new Connection() class use the old Connection() class.
How can I achive this ?
Save it as static variable in your App class, and do something like this:
public class App extends Application {
private static Connection connection;
public Connection getConnectionInstance() {
if (connection == null)
connection = new Connection();
return connection;
}
}
And in your intent service do:
((App)getApplication()).getConnectionInstance();
Don't forgot to declare this class as your application class.
<application
android:name="your.package.name.App"
android:label="#string/app_name"
android:theme="#style/AppTheme">
I'm trying to capture the ACTION_MEDIA_BUTTON intent using a broadcastreceiver in Android 3.0+.
My receiver is a static inner class of my MainActivity class. It is static, because it is registered in my AndroidManifest.xml and it has to find the class. However, this means that my BroadcastReceiver has no way of getting back to my activity when the play/pause button is pressed. The onReceive method gets called, but because the class is static, I can't inform my activity.
Using a reference to my activity or a Handler object also does not work, since I can't acquire the BroadcastReceiver object that is being called by the Android system.
Dynamically declaring the receiver should also work, but this does not work on Android 3.0+, for some strange reason. It has something to to with:
AudioManager.registerMediaButtonEventReceiver(ComponentName)
Which is required to be called.
Some illustration of my class:
public class MainActivity extends Activity {
public static class MicReceiver extends BroadcastReceiver {
// onReceive is called
// How do I inform MainActivity of the press?
}
}
Do you have any ideas for a fix?
Thanks!
[EDIT]
See my code below for registering my receiver dynamically: (This is currently not working)
mReceiver = new RemoteControlReceiver();
IntentFilter filter = new IntentFilter(Intent.ACTION_MEDIA_BUTTON);
filter.setPriority(2147483647);
registerReceiver(mReceiver, filter);
AudioManager am = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
am.registerMediaButtonEventReceiver(new ComponentName(getPackageName(), RemoteControlReceiver.class.getName()));
AFAIK, registerMediaButtonEventReceiver() is if you want to receive media button events in the background. A foreground activity can find out about media button events using the standard onKeyDown() callback.
Declaring receiver in Manifest will try to instantiate the receiver and call onRecieve(), even when activity is not around.
To make it an activity bound receiver, make it a non static class and instantiate it in onCreate(). Then, register and unregister it in onResume() and onPause() respectively. Since class is non static and registered only when activity is active, you can safely call parent activity methods from inner receiver class.
The code should look like this if you want to process something in BroadcastReceiver
public class MainActivity extends Activity {
public static class MicReceiver extends BroadcastReceiver {
public MicReceiver() {
// TODO Auto-generated constructor stub
super();
}
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
String intentAction = intent.getAction();
if (!Intent.ACTION_MEDIA_BUTTON.equals(intentAction)) {
return;
}
KeyEvent event = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
if (event == null) {
return;
}
int action = event.getAction();
if (action == KeyEvent.ACTION_DOWN) {
Toast.makeText(context, "BUTTON PRESSED! ", Toast.LENGTH_SHORT).show();
}
abortBroadcast();
}
}
}
I have an activity which displays some data fetched from the server. If no connection is available, activity displays some cached data; if connection is available, activity fetches data and displays it. It all works as expected.
Now, I would like to make my activity reload the data as soon as the connection occurs. I am using a simple Receiver that extends the BroadcastReceiver:
public class ConnectionChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
ConnectivityManager connectivityManager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
if (activeNetInfo != null) {
//what to do here?
}
}
}
Broadcast receiver is declared in my manifest file as follows:
<receiver android:name=".ConnectionChangeReceiver"
android:label="NetworkConnection">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
</intent-filter>
</receiver>
In my activity, I register the receiver:
ConnectionChangeReceiver receiver = new ConnectionChangeReceiver();
this.registerReceiver(receiver,
new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
Now, I am confused as what to do next. When onReceive method is executed, how to make my activity aware of that? I know I could start a new activity, but that's not really what I want. Should I declare ConnectionChangeReceiver as a private class of my activity? Or is there any other solution?
I think building the receiver as a private subclass of your activity is the way to go here. This way you can control events and data from your activity. Then you can just create one instance of it and register the receiver from code as you did above.
Note that you don't have to register your receiver in both the manifest and code. One of these is enugh - the manifest is basically a "static" registration while doing it in code allows dynamic registration at runtime. Also when you register in the manifest, a new instance of your receiver will automatically be created from the system, executed and terminated. Doing the reg in code allows to point to one specific instance.
Interface Approach!
You can communicate via an interface as well. This approach works even
if your BroadcastReceiver is in a seperate file. You will not even
have to access UI elements of Activity in the Broadcast.
Its pretty Straightforward. Just follow these 3 simple steps.
1) Create an interface
public interface MyListerner{
public void performSomething(String arg);
}
2) Initialize the Listener in ConnectionChangeReceiver
public class ConnectionChangeReceiver extends BroadcastReceiver {
private MyListerner listener;
#Override
public void onReceive(Context context, Intent intent) {
listener = (MyListerner )context; // initialse
ConnectivityManager connectivityManager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
if (activeNetInfo != null) {
listener.performSomething("Some data"); // Call listener method
}
}
}
3) Implement the interface and Override the method in your Activity
public class YourActivity implements MyListerner{
// Activity relate stuff onCreate() etc
public void updateUI(String result){
// Your code to update UI
}
#Override
public void performSomething(String arg){
updateUI(arg);
}
}
Relevant Links:
You can read in detail Why using an interface is a preferred approach in this case