I'm trying to catch a clipboardChanged event in a background service
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent i = new Intent(MainActivity.this, TranslateService.class);
startService(i);
}
}
public class TranslateService extends IntentService implements ClipboardManager.OnPrimaryClipChangedListener {
public TranslateService() {
super(null);
}
public TranslateService(String name) {
super(name);
ClipboardManager manager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
manager.addPrimaryClipChangedListener(this);
}
#Override
protected void onHandleIntent(Intent intent) {
}
#Override
public void onPrimaryClipChanged() {
Toast.makeText(this, "Working", Toast.LENGTH_LONG).show();
}
}
It should make a toast "Working" if the event is fired.
I also tried to create the ClipboardManager and add the listener in onHandleIntent and it didn't work either.
Any ideas?
When the default constructor is called, you are not adding the listener to ClipboardManager.
I think you meant to use this(null) in your default constructor instead of directly calling super(null).
public TranslateService() {
this(null);
}
Related
I have codes in two classes
First class is ExampleBroadcastReceiver:
public class ExampleBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
boolean noConnectivity = intent.getBooleanExtra(
ConnectivityManager.EXTRA_NO_CONNECTIVITY, false
);
if (noConnectivity) {
Toast.makeText(context, "Disconnected", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, "Connected", Toast.LENGTH_SHORT).show();
}
}
}
}
Second class is MainActivity:
public class MainActivity extends AppCompatActivity {
ExampleBroadcastReceiver exampleBroadcastReceiver = new ExampleBroadcastReceiver();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onStart() {
super.onStart();
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(exampleBroadcastReceiver, filter);
}
#Override
protected void onStop() {
super.onStop();
unregisterReceiver(exampleBroadcastReceiver);
}
}
How can I make the two classes into one by passing the code from the ExampleBroadcastReceiver class to MainActivity? Is it possible? Please don't ask why. Thanks.
Use java interface to handle an event in MainActivity that occurs in ExampleBroadcastReceiver. This way you don't have to merge classes to share an event based data.
public class ExampleBroadcastReceiver extends BroadcastReceiver {
public interface ConnectivityMonitorCallback {
void onConnectivityChanged(boolean connectivity);
}
public ConnectivityMonitorCallback callback;
public ExampleBroadcastReceiver(#NonNull ConnectivityMonitorCallback eventCallback) {
callback = eventCallback;
}
#Override
public void onReceive(Context context, Intent intent) {
if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
boolean noConnectivity = intent.getBooleanExtra(
ConnectivityManager.EXTRA_NO_CONNECTIVITY, false
);
callback.onConnectivityChanged(noConnectivity);
}
}
}
Finally in the MainActivity you handle the event.
public class MainActivity extends AppCompatActivity {
ExampleBroadcastReceiver exampleBroadcastReceiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Define event handling code here which occurs in ExampleBroadcastReceiver
exampleBroadcastReceiver = new ExampleBroadcastReceiver(new ExampleBroadcastReceiver.ConnectivityMonitorCallback {
#Override
void onConnectivityChanged(boolean connectivity) {
// Handle the event that occured in ExampleBroadcastReceiver
}
});
}
#Override
protected void onStart() {
super.onStart();
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(exampleBroadcastReceiver, filter);
}
#Override
protected void onStop() {
super.onStop();
unregisterReceiver(exampleBroadcastReceiver);
}
}
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");
}
}
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();
}
});
}
}
In MainActivity I have a TextView: textV1. I also have a method in MainActivity that updates that textview:
public void updateTheTextView(final String t) {
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
TextView textV1 = (TextView) findViewById(R.id.textV1);
textV1.setText(t);
}
});
}
In a BroadcasrReceiver I need to update the text in textV1 in MainActivity.
public class NotifAlarm extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// other things done here like notification
// NEED TO UPDATE TEXTV1 IN MAINACTIVITY HERE
}
}
How can this be done? The BroadcastReceiver is run from a service. This code I cannot change. Can I access and change textV1 in MainActivity from onReceive()? I've tried many things but all fail.
In your MainActivity initialize a variable of MainActivity class like below.
public class MainActivity extends Activity {
private static MainActivity ins;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ins = this;
}
public static MainActivity getInstace(){
return ins;
}
public void updateTheTextView(final String t) {
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
TextView textV1 = (TextView) findViewById(R.id.textV1);
textV1.setText(t);
}
});
}
}
public class NotifAlarm extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
try {
MainActivity .getInstace().updateTheTextView("String");
} catch (Exception e) {
}
}
}
#Use Interface
Another way to deal with this situation is by using an Interface. I will describe the advantage of this approach but first, let's see how it's done.
Follow these steps:
1) Create an interface
public interface MyBroadcastListener{
public void doSomething(String result);
}
2) Initialize the listener in BroadCastReceiver
public class NotifAlarm extends BroadcastReceiver {
private MyBroadcastListener listener;
#Override
public void onReceive(Context context, Intent intent) {
listener = (MyBroadcastListener)context;
// other things done here like notification
// NUPDATE TEXTV1 IN MAINACTIVITY HERE
listener.doSomething("Some Result");
}
}
3) Implement the interface in Activity and override the method
public YourActivity extends AppCompatActivity implements MyBroadcastListener{
// Your Activity code
public void updateTheTextView(String t) {
TextView textV1 = (TextView) findViewById(R.id.textV1);
textV1.setText(t);
}
#Override
public void doSomething(String result){
updateTheTextView(result); // Calling method from Interface
}
}
##Advantages of using the interface?
When you have BroadcastReceiver in a different file
Decoupled BroadcastReceiver
Using an interface makes BroadcastReceiver independent of any
Activity. Let's say in future you want to use this BroadCastReceiver
with another Activity which takes the result from BroadcastReceiver
and start a DetailActivity. This is completely a
different task but you will use the same BroadcastReceiver without even
a single code change inside BroadcastReceiver.
How to do that?
Implement the interface in the Activity and Override the method. That's it!
public ListActivity extends AppCompatActivity implements MyBroadcastListener{
// Your Activity code
public void startDetailActivity(String title) {
Intent i = new Intent(ListActivity,this, DetailActivity.class);
i.putExtra("Title", title);
startActivity(i);
}
#Override
public void doSomething(String result){
startDetailActivity(String title); // Calling method from Interface
}
}
create an instance of the class and then pass the value to the function that changes TextView value follow these steps please :
in your BroadcastReceiver overRide onReceive method and paste These lines or changes theme as you wish
private Handler handler = new Handler(); // Handler used to execute code on the UI thread
// Post the UI updating code to our Handler
handler.post(new Runnable() {
#Override
public void run() {
//Toast.makeText(context, "Toast from broadcast receiver", Toast.LENGTH_SHORT).show();
YourActivityToUpdate.updateTheTextView(message);
YourActivityToUpdateinst = YourActivityToUpdate.instance();
if(inst != null) { // your activity can be seen, and you can update it's context
inst.updateTheTextView(message);
}
}
});
now we explain the updateTheTextView and inst
in YourActivityToUpdate class Paste these Lines please
private static SignUpVerify mInst;
public static SignUpVerify instance() {
return mInst;
}
#Override
public void onStart() {
super.onStart();
mInst = this;
}
#Override
public void onStop() {
super.onStop();
mInst = null;
}
and this is the updateTheTextView method that should be placed in YourActivityToUpdate class
public void updateTheTextView(final String verifyCodeValue) {
Log.i("verifyCodeValue", verifyCodeValue);
YourTextViewToUpdate.setText(verifyCodeValue);
}
i think this is a better way thanks to "kevin-lynx"
If someone is searching this exact solution, but in Kotlin, do the following:
class MainActivity : AppCompatActivity() {
companion object {
var ins: MainActivity? = null
fun getInstance(): MainActivity? {
return ins
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
ins = this
}
fun updateTheTextView(t: String) {
this#MainActivity.runOnUiThread {
val textV1 = findViewById<TextView>(R.id.textV1)
textV1.text = t
}
}
}
class NotifAlarm : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
try {
MainActivity.getInstance()?.updateTheTextView("The String")
} catch (e: Exception) {
}
}
}
In your broadcastreceiver class send broadcast
public class mybroadcaster extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
context.sendBroadcast(new Intent("updatetext"));
}
}
In your activity register your broadcastreceiver and call it, do your work at onReceive and unregister the broadcaster in onDestroy()
public class MyActivity extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
registerReceiver(broadcastReceiver, new IntentFilter("updatetext"));
}
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// do your work here
}
};
#Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(broadcastReceiver);
}
}
Edit 1
I need to call a method from BroadcastReceiver and method exist in the Activity class mention below.
I tried this code and got NULL_POINTER_EXCEPTION where I create the reference the MainActivity class.
Correct me what I'm doing wrong ?
MainActivity.java
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void myTesting(){
Toast.makeText(MainActivity.this, "Welcome to Activity", Toast.LENGTH_SHORT).show();
}
}
BroadcastReceiver.java
public class BootCompeteReceiver extends BroadcastReceiver {
public Context mContext;
private MainActivity mainActivity;
#Override
public void onReceive(Context context, Intent intent) {
mContext = context;
try {
mainActivity = new MainActivity();
mainActivity.myTesting();
} catch (Exception e) {
Toast.makeText(context, ""+e, Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
Do something like that:
public class MainActivity extends Activity {
private BroadcastReceiver receiver = new BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
try {
MainActivity.this.myTesting();
} catch (Exception e) {
Toast.makeText(MainActivity.this, ""+e, Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IntentFilter intFilt = new IntentFilter(Constants.YOUR_BROADCAST_RECEIVER_ACTION);
registerReceiver(receiver, intFilt);
}
public void myTesting(){
Toast.makeText(MainActivity.this, "Welcome to Activity", Toast.LENGTH_SHORT).show();
}
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);
}
}
You can startActivity in onReceive, and call myTesting in onCreate of your Activity.
You can try this:
public class MainActivity extends Activity {
private static volatile int INSTANCE_COUNTER = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
INSTANCE_COUNTER++;
IntentFilter intentFilter = new IntentFilter("com.your.package.ACTION");
registerReceiver(mWhateverReceiver, intentFilter);
if (getIntent().getBooleanExtra("fromYourReceiver", false)) {
myTesting();
}
}
private void myTesting() {
// Do something here
}
private BroadcastReceiver mWhateverReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
myTesting();
}
};
public static boolean isInstanceExist() {
return INSTANCE_COUNTER > 0;
}
#Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
INSTANCE_COUNTER--;
unregisterReceiver(mWhateverReceiver);
}
}
Your receiver
public class BootCompeteReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (MainActivity.isInstanceExist()) {
// There is already one instance of MainActivity, so broadcast this
// event to trigger the receiver inside MainActivity to do your task
Intent broadcastIntent = new Intent("com.your.package.ACTION");
context.sendBroadcast(broadcastIntent);
} else {
// There is no instances of MainActivity exist, so start a new one
// with the action that let the instance know what it should do
Intent activityIntent = new Intent(context, MainActivity.class);
activityIntent.putExtra("fromYourReceiver", true);
activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(activityIntent);
}
}
}