"Calling" UI activity method from a class - android

I have an Activity which mainly handles the UI, and I do most of the rest from another class (not a service). One of the things I do from that class is playing audio. What I need to do is tell my Activity when the audio finished playing (OnCompletionListener).
public class MyClass implements OnCompletionListener {
private MyActivity activity = new MyActivity();
public MyClass(){
}
...........
...........
...........
#Override
public void onCompletion(MediaPlayer mp) {
activity.onComplete();
}
}
This is wrong because "Cannot make a static reference to the non-static method onComplete() from the type MyActivity.
I'm pretty sure I'm using Java wrong, but I cant figure out how to call onComplete from the class. (changing onComplete to static isn't posible).
EDIT:
added a constructor to MyActivity:
public MyActivity(){
}
and created an instance of MyActivity, activity (see the edited code above), passed it to the method, but when I do activity.onComplete(); it stops unexpectedly. (I dont know why my logcat isnt working, I'll post back when I get it to work)

Just pass an instance of MyActivity to MyClass and call a method on it. It's arguable approach but best I can suggest having information that you provided.

Related

Getting instance of MainActivity

Hi I am kind of new to android, still learning. And my problem is that, for example I have a method which was created in the MainActivity and I need to call it from another class.
Is it a good practice to get the instance of the MainActivity so that I may be able to call the method in the MainActivity from another class?
This is an example:
public class MainActivity extends AppCompatActivity {
private static MainActivity inst;
public static MainActivity instances()
{
return inst;
}
#Override
public void onStart() {
super.onStart();
inst = this;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void showToast (String text){
Toast.makeText(inst, text, Toast.LENGTH_SHORT).show();
}
Then this is the other class:
public class broadcastReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
MainActivity instance = new MainActivity();
instance.showToast(AnyText);
}
}
I saw this type of coding while looking at tutorials and wondered if it's a good practice or maybe there might be a better way? Since I get the warning of Do not place Android Context Classes in static classes
Thanks in advance for any insight or help! :D
I guess You want to make A singleton of Activity Class
but as Mention in All Pattern Design
using Singleton
If and Only If its only way to Make A Global Variable
Singleton is based on Lazing Initialing and Load On Memory
so I guess If you cant to Interact With Activiy You can Use
BroadCast Or Intents
You can call method from another class like this:
MainActivity instance = new MainActivity();
String data = instance.data();
and create data method in that class:
public String data() {
return mangaId;
}
Is it a good practice to get the instance of the MainActivity so that
I may be able to call the method in the MainActivity from another
class?
You totally can do this but you don't need to make it static and use a constructor. Just create a new instance like follows and you'll access the public methods
MainActivity mainActivity = new MainActivity();
mainActivity.showToast(text);
About the warning
It suggests avoiding having context fields defined as static. The warning itself explains why: It's a memory leak. If you make it static it will be accessible anywhere in your app and some methods can hold the reference to this context for a really long time and it won't be garbage collected. It will lead to a outofmemory exception and the app could crash. But here you're trying to invoke showToast() from broadcastreceiver so you can just get rid of static references. And it you need them in the future you safe ways to inject context
You cannot create instances of an Activity using the new operator.
You have to use an Intent to let an Activity to be created.
So you cannot get a reference to an instance of your activity.
The only methods you can use of your activity class are static ones.

Can I use a callback method from a BroadcastReceiver?

Learning to use the BroadcastReceiver class in Android, I have written a small program to receive the battery charge state and write it to three TextView fields in an activity.
However, I have made the BroadcastReceiver as a separate class to make it more simple and separate from the activity. Therefore I have to find a method to tell my Activity class that the battery data has been updated, or, which is my solution, to pass in references to the TextView fields from the Activity to the BroadcastReceiver class.
Does anyone know whether it is possible to make a callback method from the BroadcastReceiver to start a function, f.ex. updateTextViews(); in the Activity?
Here is the source code - note there are two java files:
http://pastebin.com/qjCTsSuH
Regards, Niels.
What worked a charm for me is simply declaring the interface objects as static. Bear in mind though that statics can cause as many problems as they solve as statics persist therir values accross instances.
public class MainActivity extends AppCompatActivity implements SocketMessageReceiver.ISocketMessageReceiver {
//Declare the cb interface static in your activity
private static SocketMessageReceiver.ISocketMessageReceiver iSocketMessageReceiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
//Assign this
iSocketMessageReceiver = this;
socketMessageReceiver.registerCallback(iSocketMessageReceiver);
}
#Override
public void sendSocketMessage(String socketMessage) {
lblEchoMessage.setText(socketMessage);
}
}
And in your Receiver ....
public class SocketMessageReceiver extends BroadcastReceiver {
interface ISocketMessageReceiver {
void sendSocketMessage(String socketMessage);
}
//Also declare the interface in your BroadcastReceiver as static
private static ISocketMessageReceiver iSocketMessageReceiver;
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals("com.WarwickWestonWright.SocketExample.RECEIVE")) {
iSocketMessageReceiver.sendSocketMessage(intent.getBundleExtra("DATA").getString("DATA"));
}
}
public void registerCallback(ISocketMessageReceiver iSocketMessageReceiver) {
this.iSocketMessageReceiver = iSocketMessageReceiver;
}
}
I have made the BroadcastReceiver as a separate class to make it more simple
IMHO, you made it more complex.
Therefore I have to find a method to tell my Activity class that the battery data has been updated, or, which is my solution, to pass in references to the TextView fields from the Activity to the BroadcastReceiver class.
Option #1: Just go back to using an inner class for the BroadcastReceiver. ACTION_BATTERY_CHANGED can only be used via registerReceiver() anyway. Just have onReceive() call some method on the activity to do the work of updating the UI.
Option #2: Pass your activity into the constructor of the BroadcastReceiver, and call the method as in option #1.
Option #3: Use an event bus, like Square's Otto or greenrobot's EventBus.

Callback to activity from other class

I have Activity class, Controller class (normal java class use to control number of activity) and BusinessEngine class (normal java class use to process data).
When I need to do some calculation from activity, Activity will call Controller and Controller will call BusinessEngine to do the calculation. When BusinessEngine done with the calculation, it will pass the value back to Controller and finally let the activity know the calculation is complete.
The problem is how I callback Activity from Controller class? Or pass any data to Activity and notify it the data has been change?
Any "long" running tasks must be performed in a background thread. I'm not sure if your currently doing this for your task, so just in case your not, there are a couple of ways to do this. The first is to simply use a AsyncTask, the second is to create your own instance of AbstractExecutorService (AsyncTask uses ThreadPoolExecutor) and use that to post Runnable or Callables to. The later way may save you a lot of re factoring depending on your code base.
Assuming you're now running the task in a background thread, it's necessary to perform your UI updates on the UI thread. There are again a couple of ways to do this. One method is to post a runnable to the method Activity#runOnUiThread, the second is to use a Handler which has previously been created on the UI thread (which Activity#runOnUiThread does behind the scenes).
So, assume your Activity has a method #postResults(final Object o), and your controller has the method #doSomething(final Activity activity).
Your activity would look something like this.
public class MyActivity extends Activity {
Controller controller = ....
ExecutorService service = Executors.newFixedThreadPool(10);
private void startTask() {
Runnable r = new Runnable() {
public void run() {
c.doSomething(MyActivity.this);
}
}
service.submit(r);
}
public void postResults(final Object o) {
Runnable r = new Runnable() {
public void run() {
// Update your UI here
}
}
runOnUiThread(r)
}
}
and your controller
public class Controller {
public void doSomething(final Activity activity) {
// Perform some long running task here
activity.postResults(someObject);
}
}
Obviously this example could be tidied up (for example passing a interface to doSomething rather than the Activity), but hopefully it should be enough to understand what you need to do :)
Why are you looking for the controller to call you Activity? Normally, your Activity must call the controller via its methods and directly get results from them:
// Code in your Activity
result = controller.doSomething(args);
try using a android AsyncTask, if your method takes a long time to process. example
Add your classes to an Async task or if you're calling the classes and passing them from one class to the other.I would say to use static class. And provide some code so we can know how you are passing your data.
If not use general methods to call the superclass or the subclass.
My answer is a bit abstract as information is less.

how to call method in service in android

I have created a service for TweetCollectorService. I want to call a method of another class in my service.can I do this Plz Help me.
Thankyou
Yes you can.. Only difference here is the method execution also occurs in background process.. No other difference..
Its not best practice to have other utility functions/methods in Activity, which mainly is to handle user interaction. so Strictly follow java convention and create different class which has all these methods, so it achieves cohesion.
You can dosomething like below..
Class YourActivity extends Activity{
public void do(){
// do your task
}
and in service just say new YourActivity().do()
}
Yes you can able to call the other class method. If you using your custom class then create the method as static so no need to create object of that class
suppose your custom class which extend Activity or not then also you can do like this way.
class CustomClass extends Activity{
public static void mymethod(){
// call me
}
}
now you can call into the service like this way without creating any object as explicitly
class MyService extends Service{
onCreate(){
CustomClass.mymethod();
}
}

Noob question about "Hello World" Android tutorial

Just getting started with Android development and Java. So, here's the code I'm working with:
package com.example.helloandroid;
import android.app.Activity;
import android.os.Bundle;
public class HelloAndroidActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
What is the purpose of declaring the onCreate() method here:
public void onCreate(Bundle savedInstanceState) {
Then using super to call the onCreate() method here:
super.onCreate(savedInstanceState);
Doesn't this mean that you are calling the onCreate() method from the Activity class rather than the HelloAndroidActivity class? If so, what is the point of declaring a method with the same name in the HelloAndroidActivity class?
Thanks for any clarification.
In your example, HelloAndroidActivity is a class that inherits from Activity. You are then overriding the base class (Activity)'s onCreate method. Overriding occurs when you define a method in a derived class with the same signature as an existing method in the base class. This means that when I call onCreate on an instance of HelloAndroidActivity, I will execute the HelloAndroidActivity version, and not the base class (Activity)'s version.
The instruction super.OnCreate(savedInstanceState) in the overridden version is explicitly calling the base class's version of the method. What this means is you want HelloAndroidActivity.onCreate to first execute the base class's implementation, then run some more code.
Take the following examples to illustrate this behavior (assume the method Output just outputs something to the screen):
1.
class A
{
public void DoSomething()
{
Output("A");
}
}
In this case, calling A.DoSomething() will output "A".
2.
Assume we still have the class A defined as above, and the following:
class B extends A
{
}
In this case, calling B.DoSomething() will also output "A".
3.
Assume we still have the class A defined as above, and the following instead:
class B extends A
{
#Override
public void DoSomething()
{
Output("B");
}
}
Now, calling B.DoSomething() will output "B".
4.
Assume we still have the class A defined as above, and now this instead:
class B extends A
{
#Override
public void DoSomething()
{
super.DoSomething();
Output("B");
}
}
Now, calling B.DoSomething() will output "A" and then "B".
You are creating a class that inherits from Activity; but you have to define its behaviour, so you tell your class, when created, to call base class to complete all the things that must be done (super.onCreate()), then you set your layout to show your screen/app (setContentView()).
One thing more: take a look at #Override defined right before public void onCreate(Bundle savedInstanceState): override means that you're extending base method to let your derived class do all the work of the base one, including (after) your logic.
Question: What is the purpose of declaring the onCreate() method here?
Answer: The oncreate() method is analogous to main(String args[]) in ususal JAVA. The oncreate activity is called when your Activity starts. So all the initialisations should be done in this method.
You write: public class HelloAndroidActivity extends Activity
This means that you are creating a class - "HelloAndroidClass" that inherits from class = "Activity".
You write: super.onCreate(savedInstanceState);
Java uses the keyword "super" to call constructors from parent class. You are using the concept of overriding here. When you run your code, the oncreate method of base class "HelloAndroidActivity" is executed and not that of parent class - "Activity class".
So you code will first run the base class implementation of oncreate() method(super.oncreate(...)) and then the implementation of derived class.
Question: What is the point of declaring a method with the same name in the HelloAndroidActivity class?
Answer: The super keyword is being used to initialize the objects. The point in redeclaring the same method and using overiding is that you are saved from rewriting the code of base class.
onCreate is sort of your main(String[] args) function in normal Java. It is where you setup your code.
From documentation for onCreate method:
Derived classes must call through to the super class's implementation of this method. If they do not, an exception will be thrown.
See more here for activity methods, lifecycle etc.

Categories

Resources