I an trying to create an application thet will catch the incoming calls to the cellphone using a BroadcastReciver. From my BroadcastReciver i whould like to sent the number as an event to my JS file using this method.
I have checked that my Java code is working and is catching the calls and number but my application craches with the error that mentions that the react context is null. I am guessing that this is because the manifest (or something) is creating a new instance of the class when the event from the android system is catched and that the new instance does not have a ReactContext. Is there any way to access the ReactContext from the Java code or send a ReactContext to the BroadcastReciver through the manifest?
This is my BroadcastReciver:
package com.bridgetest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.facebook.react.bridge.JavaScriptModule;
import android.widget.Toast;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.Arguments;
import javax.annotation.Nullable;
/**
* Created by Erik on 2016-04-06.
*/
public class BroadcastReceiverCustom extends BroadcastReceiver {
ReactContext reactContext;
public BroadcastReceiverCustom (){
}
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_RINGING)) {
// This code will execute when the phone has an incoming call
// get the phone number
String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
Toast.makeText(context, "Call from:" +incomingNumber, Toast.LENGTH_LONG).show();
sendCallEvent(incomingNumber);
} else if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(
TelephonyManager.EXTRA_STATE_IDLE)
|| intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(
TelephonyManager.EXTRA_STATE_OFFHOOK)) {
// This code will execute when the call is disconnected
Toast.makeText(context, "Detected call hangup event", Toast.LENGTH_LONG).show();
}
}
public void sendCallEvent(String incomingNumber){
WritableMap params = Arguments.createMap();
params.putString("Number", incomingNumber);
sendEvent("CallRecevied", params);
}
private void sendEvent(String eventName,
#Nullable WritableMap params) {
reactContext
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(eventName, params);
}
}
As Fury's solution did not work for me(got "cannot find symbol" for getApplication()) in the broadcast receiver, i tried applying a similar logic with what i knew is working. So:
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.ReactApplication;
...
// context - is the context you get from broadcastreceivers onReceive
ReactApplication rnApp = (ReactApplication) context.getApplicationContext();
rnApp.getReactNativeHost().getReactInstanceManager()
.getCurrentReactContext().getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit("test", Arguments.createMap());
This worked for me.
I faced a same problem and am using this.
((MainApplication)getApplication()).getReactNativeHost().getReactInstanceManager().getCurrentReactContext()
I solved the problem. I created a ReactContextBaseJavaModule with a singleton pattern and got access to ReactContext through it (This might be a huge "nono").
If there is another smarter way to solve this problem, please inform me.
You can access reactContext like this:
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.bridge.ReactContext;
ReactInstanceManager reactInstanceManager = getReactNativeHost().getReactInstanceManager();
ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
if(reactContext != null) {
// Use reactContext here
} else {
reactInstanceManager.addReactInstanceEventListener(new ReactInstanceManager.ReactInstanceEventListener() {
#Override
public void onReactContextInitialized(ReactContext context) {
// Use context here
reactInstanceManager.removeReactInstanceEventListener(this);
}
});
}
Related
Most of the search results I'm getting are for downloading cordova-plugin-camera and then calling it on the Javascript side, but is there a way to access the camera from the the java code of a custom plugin? Also is there relevant documentation for this? My code so far looks like this:
package com.ncr.cordova.camera;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaArgs;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CallbackContext;
import org.json.JSONArray;
import org.json.JSONException;
public class Camera extends CordovaPlugin{
#Override
public void initialize(CordovaInterface cordova, CordovaWebView webView) {
super.initialize(cordova, webView);
// your init code here
}
private boolean openCamera(){
//open the camera?
}
private boolean takePicture(){
//take picture?
}
#Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
switch(action){
case "helloWorld":
callbackContext.success("helloWorld");
break;
}
return false; // Returning false results in a "MethodNotFound" error.
}
}
Is there a way to implement openCamera and takePicture, or some kind of relevant functionality?
My codenameone application crashes anything I use this native code
package com.mycompany.interfaces;
import android.app.Application;
import android.content.Context;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.messaging.FirebaseMessaging;
public class InitialiseApp extends Application{
private static Context context;
public static Context getContext() {
return context;
}
#Override
public void onCreate()
{
super.onCreate();
context = getApplicationContext();
try
{
FirebaseApp.initializeApp(this, new FirebaseOptions.Builder().
setApiKey("XXXXXXXXXXXXXX").
setApplicationId("XXXXXXXX").
setGcmSenderId("XXXXXXXXXX")
.build());
FirebaseInstanceId.getInstance().deleteInstanceId();
FirebaseInstanceId.getInstance().getToken("XXXXXXXXXX",FirebaseMessaging.INSTANCE_ID_SCOPE);
FirebaseMessaging.getInstance().subscribeToTopic("test");
}
catch(Exception c)
{
c.printStackTrace();
}
}
}
I declare the class in the android.xapplication_attr android:name="com.mycompany.interfaces.InitialiseApp"
Need a assistance
Are you putting this in the native interface stub or in the CN1 part of the code?
Also, I don’t think that’s how you get a context in CN1. Look in the developer guide and video tutorials for Native Interfaces. I also recall a series of blog posts about native interfaces that dive into writing the Android code. You’ll need to use something from the AndroidNativeUtil class like: AndroidNativeUtil.getActivity().
This is a follow up to a question I asked here.
I have copied and pasted this code from this tutorial. When I paste it into Android Studio, the 'this' parameter of of content.getLoadManager.initLoader() is highlighted in red and shows the following error:
Wrong 3rd Argument Type. Found 'com.example.carl.loaderDemo.FooLoaderClient', requried: 'android.app.LoaderManager.LoaderCallBacks
I've ran into this previously (see first link). I was hoping this tutorial would help but I just seem to be going in endless circles!
Can anyone point me in the right direction?!
package com.example.carl.loaderdemo;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.Loader;
public class FooLoader extends AsyncTaskLoader {
public FooLoader(Context context, Bundle args) {
super(context);
// do some initializations here
}
public String loadInBackground() {
String result = "";
// ...
// do long running tasks here
// ...
return result;
}
}
class FooLoaderClient implements LoaderManager.LoaderCallbacks {
Activity context;
// to be used for support library:
// FragmentActivity context2;
public Loader onCreateLoader(int id, Bundle args) {
// init loader depending on id
return new FooLoader(context, args);
}
#Override
public void onLoadFinished(Loader loader, Object data) {
}
public void onLoaderReset(Loader loader) {
// ...
}
public void useLoader() {
Bundle args = new Bundle();
// ...
// fill in args
// ...
Loader loader =
context.getLoaderManager().initLoader(0, args, this);
// with support library:
// Loader loader =
// context2.getSupportLoaderManager().initLoader(0, args, this);
// call forceLoad() to start processing
loader.forceLoad();
}
}
Screenshot of error message:
There is a mismatch in your imports:
import android.support.v4.app.LoaderManager;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.Loader;
But you need
import android.app.LoaderManager;
import android.content.AsyncTaskLoader;
import android.content.Loader;
You cannot mix the support library with the android framework. Alternatively you can subclass FragmentActivity and call getSupportLoaderManager() instead.
You're implementing android.support.v4.app.LoaderManager.LoaderCallbacks but the client is expecting android.app.LoaderManager.LoaderCallbacks. You need to be consistent in which loader API you're using.
This should be very simple and I'm really not sure what is going wrong. I have created a SMSReceiver java class that basically receives messages and then gives them to my MainActivity. When the onReceive() function fires, the app crashes because it is having issues sending the data back to MainActivity. It has been throwing a NullPointerException on the Zout() call in onReceive().
Here is the SmsReceiver class:
package ...; //you don't need to see my dumb package name.
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.util.Log;
import android.widget.Toast;
import java.util.ArrayList;
public class SmsReceiver extends BroadcastReceiver {
ArrayList<String> phoneNumbers;
ArrayList<String> textMessages;
private Activity mainAct; //our reference to MainActivity
//very simple constructor
public SmsReceiver() {
}
//this function is called in onCreate() in MainActivity to provide reference to MainActivity
public void SetSMSReceiverActivity(Activity a){
mainAct = a;
//talk to our main activity
MainActivity mainComm = (MainActivity)mainAct;
mainComm.Zout("SMSReceiver initialized bro"); //this works just fine
}
#Override
public void onReceive(Context context, Intent intent) {
//THIS IS WHAT CAUSES ISSUES! This call to MainActivity does NOT work for whatever reason. Rude.
MainActivity mainComm = (MainActivity)mainAct;
mainComm.Zout("This message won't send"); //this does NOT work fine for whatever reason. Throws NullPointerException.
//...more code down here that actually works!
}
}
The function Zout() in my MainActivity is a simple print to TextView for debugging purposes. I will be using a function in MainActivity to receive the data once onReceive() stops being moody.
I'm sorry if this is a dumb question. I haven't programmed in Java for a few years and I'm quite rusty. I have no idea why this isn't working. I'll be tossing out +1's to whoever can help!
I believe it is because you have not initialized your mainAct variable.
for onCreate(){}
you do initialize
mainAct = a;
but not for onReceive.
I want to test something about usb devices, I try to write a small program, I am sure that it is wrong but this is not the point of this question.
I am sure that my imports are OK but the Android Studio refused to build this class with an error about the GetSystemService(). I have the message:
Error:(65, 43) error: cannot find symbol method getSystemService(String).
I used also an example from http://android-er.blogspot.de/2013/10/list-attached-usb-devices-in-usb-host.html and the Android Studio also has the same error but if i install the Apk from this website then it is running on my device, so i supposed that something is wrong at Android Studio.
Any good idea?
OFFTOPIC "QT Creator is light years better"
import android.content.Context;
import android.hardware.usb.UsbManager;
import android.hardware.usb.UsbAccessory;
import android.os.ParcelFileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileDescriptor;
import android.util.Log;
public class DeviceOpenActivity {
private static final String TAG = "DeviceOpenActivity";
UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
UsbAccessory mAccessory;
ParcelFileDescriptor mFileDescriptor;
FileInputStream mInputStream;
FileOutputStream mOutputStream;
public static int fibonacci(int n) {
if (n<2) return n;
return fibonacci(n-1) + fibonacci(n-2);
}
private void openAccessory() {
Log.d(TAG, "openAccessory: " + mAccessory);
mFileDescriptor = usbManager.openAccessory(mAccessory);
if (mFileDescriptor != null) {
FileDescriptor fd = mFileDescriptor.getFileDescriptor();
mInputStream = new FileInputStream(fd);
mOutputStream = new FileOutputStream(fd);
}
}
}
If you check the example that you provided, you will verify that there is a MainActivity class that extends Activity class, which by its turn extends indirectly from Context. In order to call getSystemService() you need to have an available Context. If you make your DeviceOpenActivity extend Activity, Android Studio will not complain anymore about your call.
Just leave your class declaration like this:
public class MainActivity extends Activity
Don't forget that you need to provide a XML layout for your Activity, as well as the Activity methods, like onCreate().