on click interface callback gives null in Android - java

I have Android module library which will create the Touch Keypad UI and set event listener for done and backbutton.
Also have main activity with implement eventCallback interface
MainActivity.java (Appication)
public class MainActivity extends AppCompatActivity implements eventCallback {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View v = new touchkey(this);
setContentView(v);
}
#Override
public void onClick() {
Log.i("test","complete");
Toast.makeText(this, "this is my Toast message!!! =)",
Toast.LENGTH_LONG).show();
}
}
eventCallback.java (Android Module Library)
public interface eventCallback {
void onClick();
}
touchkey.java (Android Module Library)
public class touchkey extends RelativeLayout{
private static touchkey INSTANCE;
TextView bclear;
ImageView bdone;
eventCallback eventCall;
public touchkey(Context context) {
super(context);
initialize(context);
}
public touchkey(Context context, AttributeSet attrs) {
super(context, attrs);
initialize(context);
}
public void test() {
Log.i("test","test");
}
private void initialize(Context context) {
inflate(context, R.layout.touchkey, this);
bclear = (TextView) findViewById(R.id.anti_theft_t9_key_clear);
bdone = (ImageView) findViewById(R.id.anti_theft_t9_key_done);
bdone.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (eventCall != null) {
eventCall.onClick();
}
}
});
backButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
}
}
but iam getting nullpointer exception on the touchkey.java
eventCall.onClick(); (eventCall is null)
I dont know where i am doing things wrong. can anybody help on this. Requirement: i need to handle the click event happening on the Library in Main Activity

You must create setter for eventCall (in touchkey.java):
public void setEventCall(eventCallback eventCall) {
this.eventCall = eventCall;
}
And, use it (in MainActivity):
View v = new touchkey(this);
setContentView(v);
((touchkey) v).setEventCall(this);

Related

Custom listener with interface

I am trying to understand better how to create a custom listener with a simple example but I don't know how to start the interface so that it is not null:
public class MainActivity extends AppCompatActivity implements ListenerButton{
TextView helloToOther;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
helloToOther = findViewById(R.id.helloWorldToOtherActivity);
helloToOther.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this, ButtonActivity.class));
}
});
}
#Override
public void onClickButton(View view) {
Toast.makeText(this, "Estoy en la primera activity", Toast.LENGTH_SHORT).show();
}
}
This is the second activity:
public class ButtonActivity extends AppCompatActivity {
Button btnInterface;
ListenerButton listenerButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_button);
btnInterface = findViewById(R.id.button_activity__btn__button_interface);
setUpButtonInterface();
}
private void setUpButtonInterface() {
btnInterface.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
listenerButton.onClickButton(v);
}
});
}
}
And there's the interface:
public interface ListenerButton {
void onClickButton(View view);
}
Basically I get a null pointer exception on the second activity because the interface is null, but I don't fall right now as I can start it. Thank you very much.
the reason you are getting a null pointer exception is because you haven't assigned anything to variable listenerButton and therefor it is in fact null!!
you don't need a new interface for that you just need to do this:
public class ButtonActivity extends AppCompatActivity {
Button btnInterface;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_button);
btnInterface = findViewById(R.id.button_activity__btn__button_interface);
setUpButtonInterface();
}
private void setUpButtonInterface() {
btnInterface.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//do whatever you want to do when button is clicked!
}
});
}
}
if you want to define whatever you want to do when button is clicked you need a class and not an interface:
public class ButtonListener implements View.OnClickListener{
#Override
public void onClick(View v) {
//do whatever you want to do when button is clicked!
}
}
and then in your activity do this:
public class ButtonActivity extends AppCompatActivity {
Button btnInterface;
ListenerButton listenerButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_button);
listenerButton = new ButtonListener();
btnInterface = findViewById(R.id.button_activity__btn__button_interface);
setUpButtonInterface();
}
private void setUpButtonInterface() {
btnInterface.setOnClickListener(listenerButton);
}
}
Create a new file:
MyListener.java:
public interface MyListener {
// you can define any parameter as per your requirement
public void callback(View view, String result);
}
In your activity, implement the interface:
MyActivity.java:
public class MyActivity extends Activity implements MyListener {
#override
public void onCreate(){
MyButton m = new MyButton(this);
}
// method is invoked when MyButton is clicked
#override
public void callback(View view, String result) {
// do your stuff here
}
}
In your custom class, invoke the interface when needed:
MyButton.java:
public class MyButton {
MyListener ml;
// constructor
MyButton(MyListener ml) {
//Setting the listener
this.ml = ml;
}
public void MyLogicToIntimateOthers() {
//Invoke the interface
ml.callback(this, "success");
}
}

Creating an object and running a method

Create an object and run a method:
It compiles just fine but the App crashes instantly upon launch :(
I implemented the interface and all..
What's going on?
MainActivity.java
public class MainActivity extends AppCompatActivity {
public interface MyInterfcae {
void test0();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Test t = new Test();
t.test0();
}
Test.java
public class Test extends MainActivity implements MainActivity.MyInterfcae {
public Button b = (Button)findViewById(R.id.button0);
#Override
public void test0(){
b.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
Toast toast = Toast.makeText(getApplicationContext(), "Implemented!" , Toast.LENGTH_SHORT);
toast.show();
}
});
}
It compiles just fine but the App crashes instantly upon launch :(
I implemented the interface and all..
What's going on?
public Button b = (Button)findViewById(R.id.button0);
This link gives an error. You haven't inflated the layout file related to this activity and you are trying to access button0. So, in order to resolve this error pass the layout file instance in the method and then do findViewById() using that instance.
Do like this:-
MainActivity.java
public class MainActivity extends AppCompatActivity
{
public interface MyInterfcae
{
void test0(Context context);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Test t = new Test();
t.test0(this);
}
}
Test.java
public class Test extends MainActivity implements MainActivity.MyInterfcae
{
Context context;
#Override
public void test0(final Context context)
{
this.context = context;
Button b = (Button) ((Activity)context).findViewById(R.id.button0);
b.setOnClickListener(new View.OnClickListener()
{
public void onClick(View arg0) {
Toast toast = Toast.makeText(context, "Implemented!", Toast.LENGTH_SHORT);
toast.show();
}
});
}
}

Call text to speech from class separate to activity class

I am trying to create a class which can be called from any activity to speak the text from an EditText box. When I run the code I currently have, it plays the alert sound but then fails to play the Text to Speech content. What do I need to change to get the text to play too? I know the activity layout XML code is correct because the Text To Speech code works when it is directly in the activity class. I have looked around for a solution but nowhere else outlines how to do this from a thread context.
I have included my code below:
on AircraftMain.java
View.OnClickListener speakBtnOnClickListener = new View.OnClickListener() {
#Override
public void onClick(View arg0) {
String toSpeak = textToSpeak.getText().toString();
TextToSpeak speak = new TextToSpeak(AircraftMain.this, toSpeak);
speak.run();
}
};
TextToSpeak.java
import android.app.Activity;
import android.media.MediaPlayer;
import android.speech.tts.TextToSpeech;
import java.util.Locale;
public class TextToSpeak implements Runnable {
private Activity activity;
private static String text;
private static TextToSpeech talk;
public TextToSpeak(Activity activity, String toSpeak) {
this.activity = activity;
text = toSpeak;
}
public void run() {
talk = new TextToSpeech(activity, new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if(status != TextToSpeech.ERROR) {
talk.setLanguage(Locale.UK);
}
}
});
talk.addEarcon("Attention", "com.kieronmc.aircraftgps", R.raw.warning_beep);
talk.playEarcon("Attention", QUEUE_ADD,null);
talk.setLanguage(Locale.UK);
talk.speak(text, TextToSpeech.QUEUE_ADD, null);
}
}
Try this code, It should work:
1) Create a text to speech Initializer as follows:
public class TextToSpeechInitializer{
private Context context;
private static TextToSpeech talk;
private TextToSpeechIniListener callback;
private Locale locale;
public TextToSpeechInitializer(Context context , Locale locale , TextToSpeechIniListener l) {
this.context = context;
if(l != null) {
callback = l;
}
this.locale = locale;
initialize();
}
private void initialize() {
talk = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
talk.setLanguage(locale); //TODO: Check if locale is available before setting.
callback.onSucces(talk);
}else{
callback.onFailure(talk);
Log.e("TTS","TextToSpeechInitializeError");
}
}
});
}
}
2) The above initializer class calls this interface class to notify the activity below (TTS Success or Failure) :
public interface TextToSpeechIniListener {
public void onSucces(TextToSpeech tts);
public void onFailure(TextToSpeech tts);
}
3) Activity
public class Demo7 extends AppCompatActivity implements TextToSpeechIniListener {
private Button b;
private TextToSpeechInitializer i;
private TextToSpeech talk;
private boolean flag = false;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.demo7);
i = new TextToSpeechInitializer(this, Locale.UK, this);
b = (Button) findViewById(R.id.b);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(flag) {
talk.addEarcon("Attention", getPackageName(), R.raw.androidcalm);
talk.playEarcon("Attention", QUEUE_ADD, null);
//talk.setLanguage(Locale.UK);
talk.speak("Hello, Testing", QUEUE_ADD, null);
}
}
});
}
#Override
protected void onDestroy() {
super.onDestroy();
if(talk != null){
talk.stop();
talk.shutdown();
}
}
#Override
public void onSucces(TextToSpeech tts) {
this.talk = tts;
flag = true;
}
#Override
public void onFailure(TextToSpeech tts) {
flag = false;
finish();
}
}
layout demo7.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<Button
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/b"
android:text="speak"/>
</LinearLayout>

Why ReferenceQueue always empty in activity?

I'm trying using ReferenceQueue to check Activity if the activity is destory,Whether this activity is recycled.
I just using intent to Main2Activity.class:
switch (v.getId()){
case R.id.btn_turn_two:
Intent intent=new Intent(MainActivity.this,Main2Activity.class);
startActivity(intent);
break;
default:
break;
}
when I press to return MainActivity.class, the Main2Acitivity.class will be destroyed, so I using registerActivityLifecycleCallbacks watch activity in application,
public class MainApplication extends Application{
private watche watche;
#Override
public void onCreate() {
super.onCreate();
watche=new watche(this,getApplicationContext());
}
this class is check the Activity is destoryed.
public class watche {
KeyRefrence ref;
private Context context;
private final Set<String> retainedKeys = new CopyOnWriteArraySet<>();
private final ReferenceQueue<Object> referenceQueue=new ReferenceQueue<>();
public watche(Application application, Context context){
application.registerActivityLifecycleCallbacks(lifecycleCallbacks);
this.context=context;
}
Application.ActivityLifecycleCallbacks lifecycleCallbacks=new Application.ActivityLifecycleCallbacks() {
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
#Override
public void onActivityStarted(Activity activity) {
}
#Override
public void onActivityResumed(Activity activity) {
}
#Override
public void onActivityPaused(Activity activity) {
}
#Override
public void onActivityStopped(Activity activity) {
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
#Override
public void onActivityDestroyed(Activity activity) {
//weakrefrence to this activity
String key = UUID.randomUUID().toString();
retainedKeys.add(key);
final KeyRefrence weakReference=new KeyRefrence(activity,key,activity.getPackageName(),referenceQueue);
final MyAyTask myAyTask=new MyAyTask(weakReference,activity,context);
myAyTask.doInBackground(null);
}
};
public class MyAyTask extends AsyncTask {
private Activity activity;
private KeyRefrence keyRefrence;
private Context context;
public MyAyTask(KeyRefrence keyRefrence, Activity activity,Context context){
this.activity=activity;
this.context=context;
this.keyRefrence=keyRefrence;
}
#Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);
}
#Override
protected Object doInBackground(Object[] objects) {
gc();
ref=(KeyRefrence)referenceQueue.poll();
if (ref==null){
Log.d(TAG, "onActivityDestroyed:Acitivty is not destory");
}
else if (ref!=null){
Log.d(TAG, "doInBackground: "+ref);
}
return null;
}
}
I have create KeyReference implement WeakReference,and I didn't do anything in Main2Activity.class, I just press the phone return,I check the gc,is working ,but the referencequeue always empty, I'm sure the Activity is destoryed.

change Main UI from custom Dialog Class

I have 2 class, Main and DialogOrder
Main
public class Main extends Fragment{
ImageView order;
#Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) {
order.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
new DialogOrder(getActivity()).show();
}
});
return view;
}
public void init(Bundle savedInstanceState) {
order = (ImageView) view.findViewById(R.id.order);
order.setImageResource(R.drawable.orderd);
RelativeLayout.LayoutParams orderparams = new RelativeLayout.LayoutParams(Main.screenHeight / 8, Main.screenHeight / 8);
orderparams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
orderparams.addRule(RelativeLayout.CENTER_HORIZONTAL);
orderparams.setMargins(Main.screenHeight / 80, Main.screenHeight / 80, Main.screenHeight / 80, Main.screenHeight / 30);
order.setLayoutParams(orderparams);
}
public void update_UI(){
order.setVisibility(View.INVISIBLE);
}
}
DialogOrder
public class DialogOrder extends Dialog {
Button button;
Main main;
Activity context;
public DialogOrder(Activity context) {
super(context);
this.context = context;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.order_dialog);
main = new Main();
button = (Button)findviewbyid(R.id.bd);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
main.update_UI();
dismiss();
}
});
}}
what I want is to set order image INVISIBLE when the user press the button on dialog
right now the code give me
java.lang.NullPointerException
probably I try update the UI wrong
so please can someone tell me what the right way to update parent UI class from child class ?
You can update your main fragment by passing it to Dialog constructor or you can use Listener/Callback to communicate between your main fragment and dialog.
The best practice is is using Listener/Callback because a Dialog should not have access to the caller. This is also decouple Dialog from Main fragment.
First, create the listener via interface in the dialog:
public class DialogOrder extends Dialog {
...
Activity context;
private DialogListener listener;
public interface DialogListener {
void onButtonClicked();
}
public DialogOrder(Activity context, DialogListener listener) {
super(context);
this.context = context;
this.listener = listener;
}
...
}
Then, when button click call the listener:
public class DialogOrder extends Dialog {
Activity context;
private DialogListener listener;
public interface DialogListener {
void onButtonClicked();
}
public DialogOrder(Activity context, DialogListener listener) {
super(context);
this.context = context;
this.listener = listener;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
...
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
listener.onButtonClicked();
dismiss();
}
});
}
}
Now, you can create the dialog with the listener. Something like this:
DialogOrder.DialogListener listener = new DialogOrder.DialogListener() {
#Ovveride
public void onButtonClicked() {
update_UI();
}
};
DialogOrder dialogOrder = new DialogOrder(getActivity(), listener);
dialogOder.show();
The main fragment will be listening for button clicked in the dialog.

Categories