Android make a dialogbox from an non ui-activity class - android

I don't need the code for the creation Dialog box on an activity.
I use opengles and i am drawing with the renderer class i create . I think the execution at the android activity window stays at main activity.
I have states of my drawing and when a draw reach a state i want to post a dialog box. So there is a problem with that because the dialogbox builder wants a context and the renderer class isnt an activity object.
I am new at opengles and firstly all the work i do exists at
method
public void onDrawFrame(GL10 gl)
{ }
so i have 2 classes 1st the ui class
mainactivity extends activity
and second the renderer class
class mainrenderer implements GLSurfaceView.Renderer
i want from the second class to use activity operations such as create dialog box .
Can you give me a solution to this ?
Thanks.
In other words i want from a class (renderer) that isn't ui class to make a dialogbox .
edited
i pass the context of my activity class
as myrender = new Renderer1(this);
at constructor of Renderer i have
class Renderer1 implements GLSurfaceView.Renderer
/* initializations */
public Renderer(Context context) {
super();
mcontext = context;
}
and after that i have implement the on drawFrame method and when i reach a state i call the method alertdialogbox()
given below
public void alertdialogbox() /* some code */ AlertDialog.Builder
builder = new AlertDialog.Builder(mcontext);
but it keeps erroring and application crashes when reach the state that the alertdialogbox called
the error begins with
java.lang.RuntimeException : Can't create handler inside thread that
has not called Looper.prepare()
Edit 2 solved
i initialize a handler at main activity as :
Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
alertdialogbox();
}
};
alertdialogbox is a method that i declare inside main activity class
and constructs the dialogbox
again inside the main activity where i instantiate the GlsurfaceView and the Glrenderer
i pass the handler that i initialize before so :
Renderer = new Renderer1(handler);
after that at the class Renderer1
class Renderer1 implements GLSurfaceView.Renderer
Handler mhandler;
public Renderer( Handler handler) {
super();
mhandler = handler;
}
*
*
public void onDrawFrame(){
*
*
if (state)
{
alertdialogbox();
}
}
*
*
public void alertdialogbox()
{
mhandler.sendEmptyMessage(1);
}
and finally i have my dialogbox viewed.
thanks for the suggetions .

When creating a AlertDialog (or any other UI widget) from another class, you must have a reference to your activity class and with that object, you can call activity.runOnUIThread() to execute any code related to your AlertDialog.

Related

Situation when a memory leak happens Android

I want to understand when a memory leak happens. For instance if i run this runnable in the activity, all the activity's context will be capture and if a rotation happens, the activity wont get released until the runnable terminates.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
executors.diskIO().execute(new Runnable() {
#Override
public void run() {
//CODE HERE
});
}
});
}
}
Lets say i put the runnable inside a class in a seperate file not within the MainActivity and initiate it from the activity. When a rotation happens, is there a memory leak in this case?. I mean the runnable captures the data in every rotation right?
public class A{
Data ....
public A() {}
functionB(){
executors.diskIO().execute(new Runnable() {
#Override
public void run() { }
});
});
}
}
Whenever you make an innerclass, it retains the reference of the outer class. If your runnable is inside an activity it will retain an instance to the activity and hence will result in memory leak whereas if you put it in class A it will hold reference of class A not of your activity
If you don't want to access members of the enclosing class it is preferable to make your class static as it wont hold the object of enclosing class.

Pass value from thread to main activity

I've been searching this online for a long time. Maybe what I'm doing here is wrong.
I have written a thread class in a separate file from MainActivity.java. Because both the thread and the main activity are relatively long, I decided to separate them into different files.
I wanted to pass some value generated from the thread class to the main activity. Initially I want to use handlers. But because the thread is in a different class to the main activity. It has no idea the handler I defined in the main activity.
public class mythread implements Runnable{
#Override
public void run(){
result = result_from_some_task();
}
}
This is the basic structure of my thread class and I want to pass result back to the main activity. I've looked at many examples, most of them the thread is within the main activity class and the handlers defined can be easily referred to.
Intent doesn't seems to be applicable. Does anyone have any idea on how such operations can be done?
Thanks in advance.
Make parameterized constructor of AnotherClass and when you make of object of AnotherClass then simply pass object of MainActivity into that constructor and inside AnotherClass class where you want to call MainActivity's method then simply call that method from that Object.
check following code :
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AnotherClass object= new AnotherClass (this);
object.start();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void makeSomeCalculation() {
//logic to change some UI
}
}
and check Another class :
public class AnotherClass extends Thread {
MainActivity mainActivity;
public AnotherClass (MainActivity mainActivity) {
// TODO Auto-generated constructor stub
this.mainActivity = mainActivity;
}
public void run() {
//write other logic
mainActivity.makeSomeCalculation();
//write other logic
}
}
This may not be what you are looking for so consider it as suggestion to avoid long term headaches.Try EventBus. This a library to communicate easily between various components in Android.
you need a handler in your activity. and when your thread finishes , you then dispatch a message to handler , notifying that thread execution finished. see here for example.
you can also use interface for this. see here for example. In answer, he use interface to notify from asyntask. you can do same for thread.
Your need to run the activity function within runOnUiThread.
mainActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
mainActivity.makeSomeCalculation();
}
});

Start a thread inside another thread

INTRODUCTION
I have a sub-class inside my main activity's class, which extends thread and is started every time the camera detectecs movement.
Inside this thread, when it dectects movement continuosly, it must start another thread which belongs to the main Activity's class.
I now it can be a bit messy but i'l explain it now in detail
CODE
This is a simplified version of my code that shows exactly what I mean:
public class MainActivity extends Activity {
//...
public Runnable SpeechWhenMotion = new Runnable() {
#Override
public void run() {
// Do stuff here
}
}
private static final class DetectionThread extends Thread {
//...
#Override
public void run() {
//...
//START "SpeechWhenMotion" HERE!
}
}
}
QUESTION
So the doubt I have is, how do I start the Runnable inside the thread of the DetectionThread class?
I've tryed using a handler but I think I'm not doing it right cause it doesn't get started.
If you really need SpeechWhenMotion runnable to be nester class of MainActivity you need to provide link of MainActivity or SpeechWhenMotion instance to DetectionThread class:
private static final class DetectionThread extends Thread {
private Runnable mSpeechWhenMotionRunnable;
//...
}
then, when you create DetectionThread assign SpeechWhenMotion to it from main activity
DetectionThread detectionThread = new DetectionThread();
detectionThread.mSpeechWhenMotionRunnable = SpeechWhenMotion;
And finally, call start new thread inside DetectionThread:
//START "SpeechWhenMotion" HERE!
new Thread(mSpeechWhenMotionRunnable).start();
I tried it out and this works rather smoothly:
new Thread(SpeechWhenMotion).start();

Abstract class extend Thread

First question:
How can we use
ActivityManager activity =(ActivityManager)getSystemService(ForegroundApp.ACTIVITY_SERVICE)
And also
getPackageManager in a class that extends Thread?? I'm trying to fetch the Foreground activity's package name, its start time and end time in the foreground. I know this is Context based but I need to run this is in a thread.
Second Question:
How can we call an abstract class that extends thread in a service??
This thread only runs when the screen is ON. So, I'll be registering for Screen ON and OFF intents in a service. In this service, when the screen is on, i need to call this Thread.
Example:
abstract class A extends Thread {
abstract method met();
public void run() {
//Find out foreground's app name and its start and end time.
}
}
class B extends service {
//Here i need to call A.
}
All what you have to do is simply pass an reference to your Activity in first case to class A, and reference to class A to class B. Easiest way is to pass by constructor.
abstract class A extends Thread {
protected Activity activity;
public A(Activity activity) {
this.activity = activity;
}
abstract method met();
public void run() {
// activity.yourmethods()
//Find out foreground's app name and its start and end time.
}
}

Finishing an activity from a standard java class

I am currently working on an android project and I have an activity, lets call it MyActivity and this activity calls a standard Java class called MyClass.
I need MyClass to finish the MyActivity activity but I can't find out how to do this. I thought I might be able to pass the context to the standard java class and call context.finish() but this doesn't appear to be available.
How can I do this, thanks for any help you can offer.
You can pass the Context, but you will need to cast it to an Activity (or simply pass the Activity itself), although this in general seems like a bad practice.
The most secure solution uses listener and a Handler. It is complex, but ensures a non direct call to finish activity.
Your listener:
interface OnWantToCloseListener{
public void onWantToClose();
}
Class that should close activity.
class MyClass {
private OnWantToCloseListener listener;
public void setWantToCloseListener(OnWantToCloseListener listener){
this.listener = listener;
}
private void fireOnWantToClose(){
if(this.listener != null)
listener.onWantToClose();
}
}
When you want to close your activity you must call fireOnWantToClose() method.
public MyActivity extends Activity{
public void onCreate(){
final int CLOSE = 1; //number to identify what happens
MyClass my_class = new MyClass();
final Handler handler = new Handler(){
public void handleMessage(Message msg){
if(msg.what == CLOSE)
MyActivity.this.finish();
}
});
my_class.setOnWantToCloseListener(new OnWantToCloseListener(){
public void onWantToClose(){
handler.sendEmptyMessage(CLOSE);
}
});
}
}
This is secure because Activity is not finished directly by MyClass object, it is finished through a listener that orders a handler to finish activity. Even if you run MyClass object on a second thread this code will works nice.
EDIT: CLOSE var added I forget to declare and initialize this.
Pass the MyActivity to MyClass as an Activity. From there you can call myActivity.finish();
For example:
private Activity myActivity;
public MyClass(Activity myActivity){
this.myActivity = myActivity;
}
public void stopMyActivity(){
myActivity.finish();
}
And in MyActivity:
MyClass myClass = new MyClass(this);
This is risky, because you're holding a reference to an Activity, which can cause memory leaks.
If your java class is a nested inner class, you can use:
public class MyActivity extends Activity {
public static class JavaClass {
public void finishActivity() {
MyActivity.finish();
}
}
}
Otherwise you'll have to pass the java class a Context (i.e. pass it a reference to this, since Activity extends Context) and store it as a private instance variable.

Categories

Resources