passing data from a public method to a private method error [duplicate] - android

This question already has an answer here:
What is a NullPointerException, and how do I fix it?
12 answers
I'm creating a bluetooth application and I'm trying to send a data to a private method from a public method but i got this error
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference
the public method:
public void showTimeSet(long interval, Context context){
if(interval !=0){
Toast.makeText(context,"Countdown second is "+interval,Toast.LENGTH_LONG).show();
String msg= String.valueOf(interval);
try {
sendMessage(msg);
}catch (Exception e){
Log.e(TAG, "showTimeSet Error sending message: "+e);
}
}
}
and the sendMessage method:
private void sendMessage(String message) {
// Check that we're actually connected before trying anything
if (mChatService.getState() != BluetoothService.STATE_CONNECTED) {
Toast.makeText(getActivity(), R.string.not_connected, Toast.LENGTH_SHORT).show();
return;
}
// Check that there's actually something to send
if (message.length() > 0) {
// Get the message bytes and tell the BluetoothService to write
byte[] send = message.getBytes();
mChatService.write(send);
// Reset out string buffer to zero and clear the edit text field
mOutStringBuffer.setLength(0);
mOutEditText.setText(mOutStringBuffer);
}
}

It seems the parameter context you passed into showTimeSet, is null, thus resulting in a nullpointer exception when trying to use that context for the Toast.
Check your function call for showTimeSet, and make sure context is an actual Activity/Fragment Context etc. where the toast can be displayed at.

Related

CaptureResult passed to DngSaver in ImageSaver is null camera2 api

In my quest to build a camera app using camera2api I have a small issue while trying to save a raw image.
I assign the capture result to a member in the following bit of code.
#Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
mCaptureResult = result;
Toast.makeText(getApplicationContext(),
"Image Captured",Toast.LENGTH_SHORT).show();
}
};
When I debug it at this location the member is assigned and not null. However when It throws a null error at the DngCreator in ImageSaver class.
My Listeners:
private ImageReader mImageReader;
private ImageReader.OnImageAvailableListener mOnImageAvailableListener =
new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader imageReader) {
mBackgroundHandler.post(new ImageSaver(imageReader.acquireNextImage(),mUiHandler,
mCaptureResult, mCameraCharacteristics));
}
};
private ImageReader mRawImageReader;
private ImageReader.OnImageAvailableListener mOnRawImageAvailableListener =
new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader imageReader) {
mBackgroundHandler.post(new ImageSaver(imageReader.acquireNextImage(),mUiHandler,
mCaptureResult, mCameraCharacteristics));
}
};
My Image Saver class:
private ImageSaver(Image image, Handler handler, CaptureResult captureResult,
CameraCharacteristics cameraCharacteristics) {
mImage = image;
mHandler =handler;
mCaptureResult = captureResult;
mCameraCharacteristics = cameraCharacteristics;
}
#Override
public void run() {
int format = mImage.getFormat();
switch(format){
case ImageFormat.JPEG:
ByteBuffer byteBuffer = mImage.getPlanes()[0].getBuffer();
byte[] bytes = new byte[byteBuffer.remaining()];
byteBuffer.get(bytes);
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(mImageFile);
fileOutputStream.write(bytes);
}
catch (IOException e){
e.printStackTrace();
}
finally {
mImage.close();
if(fileOutputStream != null){
try{
fileOutputStream.close();
}
catch (IOException e){
e.printStackTrace();
}
}
//Message message = mHandler.obtainMessage();
//message.sendToTarget();
}
break;
case ImageFormat.RAW_SENSOR:
DngCreator dngCreator = new DngCreator(mCameraCharacteristics,mCaptureResult);
FileOutputStream rawFileOutputStream = null;
try {
rawFileOutputStream = new FileOutputStream(mRawImageFile);
dngCreator.writeImage(rawFileOutputStream, mImage);
}
catch (IOException e){
e.printStackTrace();
}
finally{
mImage.close();
if(rawFileOutputStream != null){
try {
rawFileOutputStream.close();
}
catch (IOException e){
e.printStackTrace();
}
}
}
break;
}
}
}
Right now it gives me an error when I try to initialize the DngCreator and the stacktrace is as follows.
FATAL EXCEPTION: Camera2 Background Thread
Process: com.something.something, PID: 5162
java.lang.IllegalArgumentException: Null argument to DngCreator constructor
at android.hardware.camera2.DngCreator.<init>(DngCreator.java:89)
at com.something.something.ControlCameraActivity$ImageSaver.run(ControlCameraActivity.java:328)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.os.HandlerThread.run(HandlerThread.java:61)
Can someone please help me fix this? IF you need any more information from me do let me now. Thanks
First. When you call imageReader.acquireNextImage() set it in a Image object and after use it do a Image.close. ImageReaders are really dangerous with garbage collector and also if you have a low number in your ImageReader maxImages, you will fill it pretty fast cause you are not closing the images.
Second, about your references, where is your savingImage method? image is not a parceable object, so, if you are sending it to a service or another clase maybe you are having problems with that.
Finally, as #Eddy say, sometimes onCaptureComplete is not called before your OnImageAvailable. So, you have 2 solutions about this:
Just add a check for avoid FC in your apps:
if (mImage != null && mCameraCharacteristics != null && mDngResult != null) {
//process your dng
}
Or, you can create a a Listener. So, when you recieve your onImageAvailable(), you can put a petition in a Custom List, or Hastable.
There, check if the List have any captureResult available, if you have a CaptureResult, take it and process your DNG, if not instantiate a Listener which will be called in your onCaptureComplete. There you just need to check if the listener is null, and if it's not, make the call to "process" the image now that your result is available.
public class MyResultList {
private DngListener mDngListener;
private Hashtable<String, CaptureResult> mDngCaptureResults;
public int getSize() {
return mDngCaptureResults.size();
}
public Object getResult() {
if (mDngCaptureResults.size() == 0){
mDngListener = new DngListener() {
#Override
public void onResultAvailable() {
//Now result is not null, so you can get the available item
YourSavingImage(mDngCaptureResults.get(0));
}
}
return null;
} else {
return mDngCaptureResults.get(0);
}
}
public void add(CaptureResult result, String index){
mDngCaptureResults.put(index,result);
}
}
I just made that idea, modify it for your objetives. It's quite simple and maybe doesn't work so good if you have a lot of dependencies. Hope that anyway it will help you!
There's no guarantee that onCaptureCompleted() happens before OnImageAvailable(). In fact, since RAW image buffers are often ready earlier than the image processing for preview and result metadata completes, it's very likely that onCaptureCompleted() will happen after onImageAvailable().
If onImageAvailable happens first, you don't have a capture result yet.
Instead, you should wait for both the image and the capture result to be done, then create the ImageSaver. As one option, have both callbacks save their respective outputs (capture result and Image) in some shared location, and then check if both are non-null - if so, invoke the ImageSaver. Then it doesn't matter which runs first, the one that runs second launches the ImageSaver.

Android - Null pointer on Toast call

I have a service which calls a C function through JNI. This function then spawns a pthread and attaches it to the JVM. I call a Java method from this pthread which should post a Toast notification. Unfortunately, as soon as the Toast notification is called, I get a null pointer exception.
Here is the method that handles the Toast call in my service class:
public void showToast(final String msg) {
final Context MyContext = this;
Handler h = new Handler(MyContext.getMainLooper());
h.post(new Runnable() {
#Override
public void run() {
Toast myToast = Toast.makeText(MyContext, msg, Toast.LENGTH_SHORT);
myToast.show();
}
});
}
What could be causing the null pointer exception, and how can I fix it?
Is it trying unsuccessfully to take the context from the C function?
Here is the error message
W/dalvikvm( 4010): JNI WARNING: JNI method called with exception pending
W/dalvikvm( 4010): in Ldalvik/system/NativeStart;.run:()V (CallVoidMethod)
W/dalvikvm( 4010): Pending exception is:
I/dalvikvm( 4010): java.lang.NullPointerException:
I/dalvikvm( 4010): at android.content.ContextWrapper.getMainLooper(ContextWrapper.java:104)
Using getApplicationContext:
I/dalvikvm( 6242): java.lang.NullPointerException:
I/dalvikvm( 6242): at android.content.ContextWrapper.getApplicationContext(ContextWrapper.java:109)
Try this:
Toast.makeText(MyContext, msg, Toast.LENGTH_SHORT).show();
That's how i've always done it and it will only crash if msg isn't null.
Try that and if that doesn't work check for msg being null before. You could do something like this.
if (msg.equals(null){
msg = "Variable was null";
}
Toast.makeText(MyContext, msg, Toast.LENGTH_SHORT).show();
By the way i forgot to consider that you might not get what this means.
If you get the toast message Variable was null when you run your app. that means wherever the method call comes from is sending a null string. You need to find the method call and figure out why the variable it's passing is null.
For instance search your project for this showToast(
Search for that call, as many times as it's made. If there is more than one call you can check the string at each call before you make it, and if it's null you can add a string that will help you identify where the call came from. you can use the code i put above before each call, but checking the variable sent instead. then making it equal "call from xxxxx is null""" xxxx being the location that the call is made from. then you can figure out why the variable sent is null.
also try what i said with getApplicationContext() instead of MyContext
The problem is that, when called from a C thread through JNI, we cannot get the context. We must get the context from the Service thread itself. In order to do so:
public class MyService extends Service{
private static Context MyContext; /* get context to use when displaying toast from JNI*/
#Override
public IBinder onBind(Intent intent) {
return null;
}
public void onDestroy() {
}
#Override
public int onStartCommand(Intent intent,int flags, int startid){
MyContext = getApplicationContext();
// do what you need to
return START_STICKY;
}
public void showToast(final String msg) {
Handler h = new Handler(MyContext.getMainLooper());
h.post(new Runnable() {
#Override
public void run() {
Toast myToast = Toast.makeText(MyContext, msg, Toast.LENGTH_SHORT);
myToast.show();
}
});
}
}
This way, we have a static reference to the proper context that we can access with our call from JNI

Send an int to a paired Bluetooth device

I managed to create a ListView, search for devices and show them, on click connect to the selected device, but now I want to know how to send from one phone to the other one just an int or a boolean or something like this.
It's a little game, there is a winner and a loser - so I want to compare two variables and check who won, then display it.
My code so far:
Searching
bluetooth.startDiscovery();
textview.setText("Searching, Make sure other device is available");
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter);
Displaying in a ListView
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
device = intent
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
mDeviceList.add(device.getName() + "\n" + device.getAddress());
Log.i("BT", device.getName() + "\n" + device.getAddress());
listView.setAdapter(new ArrayAdapter<String>(context,
android.R.layout.simple_list_item_1, mDeviceList));
}
}
};
#Override
protected void onDestroy() {
unregisterReceiver(mReceiver);
super.onDestroy();
}
Pairing the devices
private void pairDevice(BluetoothDevice device) {
try {
Log.d("pairDevice()", "Start Pairing...");
Method m = device.getClass().getMethod("createBond", (Class[]) null);
m.invoke(device, (Object[]) null);
Log.d("pairDevice()", "Pairing finished.");
} catch (Exception e) {
Log.e("pairDevice()", e.getMessage());
}
}
It works pretty well, both devices are paired.
Do I need a client and a server to transfer ints?
Here is some sample code from the android SDK: BluetoothChat
The key is to use a Service on both sides of the connection that both listens for incoming messages and sends outgoing messages. Then all your Activity has to worry about is interacting with the user, and telling the service to send the appropriate messages.
//METHOD FROM ACTIVITY
private void sendMessage(String message) {
// Check that we're actually connected before trying anything
if (mChatService.getState() != BluetoothChatService.STATE_CONNECTED) {
Toast.makeText(this, R.string.not_connected, Toast.LENGTH_SHORT).show();
return;
}
// Check that there's actually something to send
if (message.length() > 0) {
// Get the message bytes and tell the BluetoothChatService to write
byte[] send = message.getBytes();
mChatService.write(send);
// Reset out string buffer to zero and clear the edit text field
mOutStringBuffer.setLength(0);
mOutEditText.setText(mOutStringBuffer);
}
}
//METHOD FROM SERVICE
public void write(byte[] out) {
// Create temporary object
ConnectedThread r;
// Synchronize a copy of the ConnectedThread
synchronized (this) {
if (mState != STATE_CONNECTED) return;
r = mConnectedThread;
}
// Perform the write unsynchronized
r.write(out);
}

Pass data from Service to Activity

I have the service that runs itself (service starts automatically).
And I have the Activity.
In this Activity button starts the method DoIt():
Button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
DoIt();
}
});
Some data is written to the variable data in my service when I push the button and method works.
I can see data in Log:
public String getMessage(String data) {
...
Log.d(TAG, "Our Data: " + data);
return date;
...
But how can I see this data in my Activity (under the button) by pushing the button?
Thanks.
There is no way you could see this data from your activity.
Making an application class would make things easier for you. You can hold your data in the application class so that the service can update it, and the activity can retrieve it. Not sure if thats what you want though.
You need to bind the service to your activity. Once the service is bound you can access the methods in your service. Look at this example for how
http://developer.android.com/guide/components/bound-services.html
You can also add a listener to your service so that you activity would be instantly notified when the data changes
Add a handler to your activity like this :-
Handler handler = new Handler() {
public void handleMessage(Message message) {
Object path = message.obj;
if (message.arg1 == RESULT_OK && path != null) {
Toast.makeText(context,
"Success" + path.toString(), Toast.LENGTH_LONG)
.show();
} else {
Toast.makeText(context, "Operation failed.",
Toast.LENGTH_LONG).show();
}
};
};
and send the value from the service in message object like this :-
Messenger messenger = (Messenger) extras.get("MESSENGER");
Message msg = Message.obtain();
msg.arg1 = data;//your value here
msg.obj = data;
try {
messenger.send(msg);
} catch (android.os.RemoteException e1) {
Log.w(getClass().getName(), "Exception sending message", e1);
}
Hope it works.

java.lang.RuntimeException: Can't create handler inside thread

I'm getting errors...Can't create handler inside thread that has not called Looper.prepare()
Actually my case is like this:
I'm trying to use the example code of "BluetoothChat" that I took from Android developer. My mission is set an app running and sending messages automatically after the remote device is connected... I think you all know what I'm trying to say...
I have String messages that I want the app send every second for remote device:
String helloString[] = {"hello person"," hi there", "hola hola", "yau yau..."};
Here I tried to change some part of the code where i think an app will do what I want with failed... :(
private void setupChat()
{
Log.d(TAG, "setupChat()");
Thread output = new Thread()
{
public void run()
{
while (true)
{
for(int i = 0; i < 4; i++)
{
//Sending helloStrings for the device
message = helloString[i];
sendMessage(message);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
}
};
output.start();
// Initialize the BluetoothChatService to perform bluetooth connections
mChatService = new BluetoothChatService(this, mHandler);
}
/**
* Sends a message.
* #param message A string of text to send.
*/
private void sendMessage(String message)
{
// TODO Auto-generated method stub
// Check that we're actually connected before trying anything
if (mChatService.getState() != BluetoothChatService.STATE_CONNECTED)
{
Toast.makeText(this, R.string.not_connected, Toast.LENGTH_SHORT).show();
return;
}
byte[] send = message.getBytes();
mChatService.write(send);
}
You need to declare #Override on run() method too.
See the accepted answer to this question How to run a Runnable thread in Android?.

Resources