My MainActivity class is big. Therefor, I want to seperate the inner class BroadcastListener into normal class but I am facing the problem that I do not know how can I access the method and varaible in the MainActivity from this BroadcastReceiver class. Is there a way to do that?
I appreciate any help.
private class BroadcastReceiverListener extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(
android.net.wifi.WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
// This method"deliverBestAccessPoint" is in MainActivity class
String a = deliverBestAccessPoint(updatedResults);
//I want to set the "textwifi" varaible in MainActivity
textWifi.setText(a.toString());
}
}
else if (intent.getAction().equals(
android.net.ConnectivityManager.CONNECTIVITY_ACTION)) {
}
}
Create one interface as
interface ReceiverInteface
{
onBroadcastReceive();
}
let mainActivity implements this interface
mainactivity implements ReceiverInterface
{
#override
onBroadcastReceive()
{
//do all you task here
}
}
And BroadCastReceiverListner Class
pass refrence of interface from Mainactiivty.
ReceiverInteface recevierListner;
BroadcastReceiverListener(ReceiverInteface mListner)
{
recevierListner = mListner;
}
private class BroadcastReceiverListener extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(
android.net.wifi.WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
recevierListner.onBroadcastReceive();
}
}
}
Related
public class ABC extends Activity{
public void foo(int val)
{
}
...
public static class Receive extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
....
}
}
...
}
can anyone help me how can i call foo() from onReceive() of Receive class
public class YourActivity extends AppCompatActivity {
static YourActivity instance;
...
...
#Override
protected void onCreate(Bundle savedInstanceState) {
instance = this;
}
...
...
public void foo() {}
static class Receiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
instance.foo();
}
}
if you cant make foo method static then you can remove the static from receive class.
public class Receive extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
}
}
Move public void foo(int val) to Class Receive
How can i make a callback to an Activity form a Java Class?
Example:
public class TestClass{
String text = "Test";
public TestClass(Context context){
startActivity(new Intent(context, SomeActivity.class));
}
private void sendToSomeActivity(){
//Call some method of SomeActivity and pas text as string
}
}
When sendToSomeActivity() is called, i want to make a callback to the already started SomeActivity and pass some text to the Activity. In SomeActivity i want to use the text.
Note: The TestClass object that i want to use is already created in another class.
How can this be done?
The solution I chose is as follows:
Use BroadcastReceivers to communicate between Java classes and Activities.
Example:
public class SomeActivity extends Activity{
private MyBroadcastReceiver receiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
receiver = new MyBroadcastReceiver();
this.registerReceiver(receiver, new IntentFilter(MyBroadcastReceiver.ACTION));
}
#Override
public void onDestroy() {
super.onDestroy();
this.unregisterReceiver(receiver);
}
private class MyBroadcastReceiver extends BroadcastReceiver{
public static final String ACTION = "com.example.ACTION_SOMETHING"
#Override
public void onReceive(Context context, Intent intent) {
String test = intent.getStringExtra("dataToPass");
}
}
}
public class TestClass{
private String test = "TEST";
private Context context;
public TestClass(Context context){
this.context = context;
}
private void sendToSomeActivity(){
Intent intent = new Intent();
intent.setAction(SomeActivity.MyBroadcastReceiver.ACTION);
intent.putExtra("dataToPass", test);
context.sendBroadcast(intent);
}
}
Try this..
public class TestClass{
interface Implementable{
public void passData(String text);
}
Implementable imple;
String text = "Test";
public TestClass(Context context){
startActivity(new Intent(context, SomeActivity.class));
}
private void sendToSomeActivity(){
if(imple != null){
imple.passData(text);
}
}
public void setListener(Implementable im){
imple = im;
}
}
class SomeActivity implements Implementable{
new TestClass().setListener(this);
#override
public void passData(String text){
//here is your text
}
}
In your java class create an interface like this
public class TestClass{
private MyInterface myInterface;
public interface OnSendSomething {
public void onSending(String sendWhateverYouWant);
}
public void setOnSendListener(MyInterface myInterface) {
this.myInterface = myInterface;
}
}
private void sendToSomeActivity(){
//Call some method of SomeActivity and pas text as string
myInterface.onSending(sendWhateverYouWant);
}
And in your activity do something like this:
TestClass tclass = new TestClass(context);
tclass.setOnSendListener(new OnSendSomething () {
#Override
public void onSending(String sendWhateverYouWant) {
//sendWhateverYouWant is here in activity
}
});
You can also visit these links for better understanding.
How to create our own Listener interface in android?
Observer Design Pattern in Java
I've set up a class called NetworkStatus that monitors the network status of the device. Within NetworkStatus I've defined a BroadcastReceiver that monitors if there has been a connectivity change, i.e., if the internet has been switched off or on. I want to 'expose' this method (i.e. onReceive) to the activity that instantiated the instance of NetworkStatus.
I'm trying to achieve this by setting up an interface in the NetworkStatus class, but I'm not sure how to call the interface from the onReceive method of the BroadcastReceiver i.e.,
public class NetworkStatus {
public static interface NetworkStatusCallbacks {
void onReceive();
}
public static class ConnectivityChange extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
// need to call NetworkStatusCallbacks onReceive here
}
}
}
Then in the main activity I would do something like,
public class MyActivity extends Activity implements NetworkStatus.NetworkStatusCallbacks {
#Override
public void onReceive() {
// Do stuff here
}
}
Would really appreciate some pointers. Thanks.
Possible Solution
Think I have found a solution. As Selvin pointed out, to do this requires the Activity. I therefore obtained the Activity by casting it from the activity context that is passed to a constructor for the NetworkStatus class, i.e., setting a constructor for the class as
private static nsc NetworkStatusCallbacks;
public NetworkStatus (Context context) {
Activity activity = (Activity) context;
nsc = (NetworkStatusCallbacks) activity;
}
I can then call the interface from the onReceive method of the BroadcastReceiver as follows:
public void onReceive(Context context, Intent intent) {
nsc.onReceive();
}
Try something like this:
public class NetworkStatus {
public static interface NetworkStatusCallbacks {
void onReceive();
}
private final NetworkStatusCallbacks m_cb;
NetworkStatus(NetworkStatusCallbacks cb)
{
m_cb=cb;
}
public static class ConnectivityChange extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
// need to call NetworkStatusCallbacks onReceive here
m_cb.onReceive()
}
}
}
MyActivity implements a CustomListener defined in MyClass.java. I have a function defined in MyClass that should trigger the listener and do some action(finish() MyActivity) defined in the activity. Somehow, I am getting null reference to the listener. Where am I going wrong?
Please refer to the code below!
MyActivity.java
import com.project.MyClass.CustomListener;
public class MyActivity extends Activity implements CustomListener {
Context context;
CustomListener listener;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = this;
myClass = new MyClass(context);
myClass.setOnCustomListener(listener);
}
public void doThisWhenTriggered()
{
...
}
}
MyClass.java
public class MyClass{
private Contect ctx;
ArrayList<CustomListener> listeners = new ArrayList<CustomListener>();
public MyClass(Context context)
{
super();
this.ctx = context
}
public interface CustomListener
{
public void doThisWhenTriggered();
}
public void setOnCustomListener(CustomListenerListener listener)
{
this.listeners.add(listener);
}
public void generateTrigger()
{
CustomListener listener = listeners.get(0);
if(listener != null)
listener.doThisWhenTriggered();
else
Log.d("MyAPP", "Listener is NULL");
}
}
MyBroadcastReceiver.java
public void onReceive(Context context, Intent intent) {
...
callMyClass(Context context)
}
public void callMyClass(Context context)
{
MyClass myClass= new myClass(context);
myClass.generateTrigger(context);
}
EDIT
The problem was BECAUSE of accessing different instances of MyClass in BroadcastReceiver and Listeners list as correctly pointed out by #Binyamin Sharet
The solution is to declare the listener list as static and also public void generateTrigger() as static so that the receiver's callMyClass looks like :
public void callMyClass(Context context)
{
MyClass.generateTrigger(context);
}
You never instantiate listener (declared as CustomListener listener;) and therefore its always null, you just need to set the activity as the listener, as it implements the interface:
myClass.setOnCustomListener(this);
As seen in your code, you create a new instance of the class in the receiver, so the listener you set does not exist in the listeners list of new instance, since the list is not static.
Its because
MyClass myClass = new myClass(context);
in MyBroadcastReceiver.java. This will create a new instance.
So I think it will be better to use MyClass.java as Singleton.
public class MyClass {
private Contect ctx;
ArrayList<CustomListener> listeners = new ArrayList<CustomListener>();
private static final MyClass singletonMyClass = new MyClass();
private MyClass() {
}
public static CustomListner getInstance() {
return singletonMyClass;
}
public interface CustomListener {
public void doThisWhenTriggered();
}
public void setOnCustomListener(CustomListenerListener listener) {
this.listeners.add(listener);
}
public void generateTrigger() {
CustomListener listener = listeners.get(0);
if (listener != null)
listener.doThisWhenTriggered();
else
Log.d("MyAPP", "Listener is NULL");
}
}
from MyActivity.java you can call
MyClass myClass = MyClass.getInstance();
myClass.setOnCustomListener(listener);
and similarly in MyBroadcastReceiver.java
public void callMyClass(Context context)
{
MyClass myClass= MyClass.getInstance();
myClass.generateTrigger();
}
Hope this helps!!!.
MAIN ACTIVITY
public class MyActivity() extends Activity
{
onCreate()
{
MyClass myobj=new MyClass();
}
public void Mymethod()
{}
}
//HELPER CLASS IN A SEPARATE FILE
public class MyClass()
{
MyClass(Context context)
{
}
}
I tried to call Mymethod() from an instance of MyClass.
I would really appreciate any help. Thanks.
Why not just pass the activity to the constructor like
public class MyActivity extends Activity {
onCreate(){
MyClass myobj=new MyClass(MyActivity.this);
}
public void myMethod(){
}
}
//HELPER CLASS IN A SEPARATE FILE
public class MyClass{
public MyClass(MyActivity act) {
act.myMethod();
}
}
Make that method as static so you can call without creating the class object
public static void Mymethod()
{}
and call like this way
MainActivity.Mymethod();
This is probably the best way to do it. This is how I'm doing it. It's called a Singleton Design Pattern:
public class MyActivity extends Activity {
private static MainActivity instance;
public static MainActivity getInstance() {
if(instance==null){
setInstance(this);
}
return instance;
}
public static void setInstance(MainActivity instance) {
MainActivity.instance = instance;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setInstance(this);
}
}
If I'm understanding you correctly I believe you can solve your problems using an interface as a callback.
////ACTIVITY/////////////////////////////////
public class MyActivity() extends Activity {
onCreate()
{
MyClass myObj=new MyClass();
//Set the listener on the object. Created as anonymous
myObj.setListener(new MyClass.Listener() {
myMethod();
});
}
}
public void myMethod(){
}
//////Custom Class//////////////////
public class MyClass {
Listener mListener;
public interface Listener {
public void onInterestingEvent();
}
public void setListener(Listener listener) {
mListener = listener;
}
public void someUsefulThingTheClassDoes() {
//Do your code here and when you're ready to call the activity's method do this
mListener.onInterestingEvent();
}
}
I had an inner class that I wanted to pull out into a more general library "Helper" class. I had the same issue you do. I got around it by making the helper class abstract, with a single abstract method. Then in my project package I extended the helper class with a constructor call in the specific class.
public class MyActivity extends Activity {
onCreate() {
MyHelperClass = new MyHelperClass(this, "foobar");
}
public void myMethod() {
// Code...
}
}
// In a different file
public class MyHelperClass extends HelperClass {
private MyActivity mInstance;
public MyHelperClass(MyActivity act, String data) {
super();
this.mInstance = act;
this.mActivity = act; // Useful for calling generic Activity methods in the HelperClass
this.mData = data;
}
protected void callMyActivityMethod() {
mInstance.myMethod();
}
}
// In a different file
public abstract class HelperClass {
protected Activity mActivity;
protected String mData;
public HelperClass() {
// Subclass will set variables
}
protected abstract void callMyActivityMethod();
// More code for all the other stuff the class does
}
In this way, I have a helper class that contains the vast majority of the "work", and all I have to do is make a subclass with the constructor and one method in order to get access to the calling activity's method of interest.
You have to pass instance of MainActivity into another class, then you can call everything public (in MainActivity) from everywhere.
MainActivity.java
public class MainActivity extends AppCompatActivity {
// Instance of AnotherClass for future use
private AnotherClass anotherClass;
#Override
protected void onCreate(Bundle savedInstanceState) {
// Create new instance of AnotherClass and
// pass instance of MainActivity by "this"
anotherClass = new AnotherClass(this);
}
// Method you want to call from another class
public void myMethod(){
...
}
}
AnotherClass.java
public class AnotherClass {
// Main class instance
private MainActivity mainActivity;
// Constructor
public AnotherClass(MainActivity activity) {
// Save instance of main class for future use
mainActivity = activity;
// Call method in MainActivity
mainActivity.myMethod();
}
}
In MainActivity.class file
You have to pass MainActivity context from MainActivity Class. Then in MyClass you have to Get MainActivity context. Remember Context and MyActivity are two different reference.
public class MyActivity extends Activity
{
onCreate(){
MyClass myobj=new MyClass(MyActivity context);
}
public void Mymethod(){}
}
//HELPER CLASS IN A SEPARATE FILE
public class MyClass()
{
MyActivity context;
MyClass(MyActivity context)
{
this.context = context;
this.context.Mymethod();
//Or you can directly use activity context
context.Mymethod();
}
}
I decided to write the HelperClass MyClass as an inner class of MyActivity class. This allows it full access to parent class but the bad thing is now MyClass is restricted to MyActivity class only.
public class MyActivity() extends Activity
{
onCreate()
{
MyClass myobj=new MyClass();
}
public void myMethod()
{
}
}
//INNER CLASS
public class MyClass
{
public MyClass()
{
}
//I can directly access the MyMethod
myMethod();
}