I get an exception while trying to write a MifareUltralight NFC tag on Android. The error shown in logcat is:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.View.setVisibility(int)' on a null object reference at
.MainActivity.getTagInfo(MainActivity.java:124)
com.mynfctest.MainActivity.resolveIntent(MainActivity.java:106)
com.mynfctest.MainActivity.onNewIntent(MainActivity.java:98)
How I can solve this error?
Write method:
public static boolean writeOnMifareUltralight(Context _context, Tag tag, String pageData, int i) {
MifareUltralight mifare = null;
int size=pageData.length();
try {
mifare = MifareUltralight.get(tag);
mifare.connect();
mifare.writePage(i, pageData.getBytes(Charset.forName("US-ASCII")));
} catch (Exception ex) {
ex.printStackTrace();
Log.d("skm", ex.getMessage());
// return false;
} finally {
try {
mifare.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
return true;
}
Write method called from my activity:
switch (mifareUlTag.getType()) {
case MifareUltralight.TYPE_ULTRALIGHT:
boolean result=NFCHammer.writeOnMifareUltralight(this,tag,tvName.getText().toString(),4);
if(result){
findViewById(R.id.incProgressBar).setVisibility(View.GONE);
Intent Callintent = new Intent(this, HomeActivity.class);
Callintent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(Callintent);
finish();
overridePendingTransition(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
}
else{
findViewById(R.id.incProgressBar).setVisibility(View.GONE);
CommonTask.createToast("Tap The card again!!!", this, Color.RED);
}
break;
}
As the exception explains, you are calling the method setVisibility on a null ob ject reference:
java.lang.NullPointerException: Attempt to invoke virtual method '... setVisibility(int)' on a null object reference
In other words, somewhere in your code, you have a like this:
object.setVisibility(...);
and on this like the variable object is null and does not reference a real object.
The stacktrace of the exception further tells you that the exception occured on line 124 of the file MainActivity.java, more specifically inside a method named getTagInfo:
at .MainActivity.getTagInfo(MainActivity.java:124)
As you did not reveal enough code to verify if the problem comes from those code snippets that you posted, we can only speculate that the problem comes from the two lines that set the visibility of a view R.id.incProgressBar to GONE:
findViewById(R.id.incProgressBar).setVisibility(View.GONE);
If that's the case, then findViewById(R.id.incProgressBar) returned null, indicating that the view R.id.incProgressBar was not found in the current view hiearchy of the activity.
Related
Hello everyone,
I try to access the storage and select an image immediately after the app crashes me and then I get the following error:
It is important to note API 29 everything works great and only when I upload the API to version 30-31 I get this error.
I have all the storage permissions
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.pets.igloopet, PID: 9797
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.io.File.exists()' on a null object reference
at com.pets.igloopet.activity.addpet.AddImage$1.onClick(AddImage.java:149)
at com.cocosw.bottomsheet.BottomSheet$4.onItemClick(BottomSheet.java:332)
at android.widget.AdapterView.performItemClick(AdapterView.java:330)
at android.widget.AbsListView.performItemClick(AbsListView.java:1197)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:3190)
at android.widget.AbsListView$3.run(AbsListView.java:4166)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7839)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
This is my code (File Addimage.java):
builder.listener(new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case R.id.camera_cards:
if (ProjectUtils.hasPermissionInManifest(getActivity(), PICK_FROM_CAMERA, Manifest.permission.CAMERA)) {
if (ProjectUtils.hasPermissionInManifest(getActivity(), PICK_FROM_GALLERY, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
try {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File file = getOutputMediaFile(1);
if (!file.exists()) {
try {
ProjectUtils.pauseProgressDialog();
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
//Uri contentUri = FileProvider.getUriForFile(getApplicationContext(), "com.example.asd", newFile);
picUri = FileProvider.getUriForFile(getActivity().getApplicationContext(), getActivity().getApplicationContext().getPackageName() + ".fileprovider", file);
} else {
picUri = Uri.fromFile(file); // create
}
sharedPrefrence.setValue(Consts.IMAGE_URI_CAMERA, picUri.toString());
intent.putExtra(MediaStore.EXTRA_OUTPUT, picUri); // set the image file
startActivityForResult(intent, PICK_FROM_CAMERA);
} catch (Exception e) {
e.printStackTrace();
}
}
}
break;
case R.id.gallery_cards:
if (ProjectUtils.hasPermissionInManifest(getActivity(), PICK_FROM_CAMERA, Manifest.permission.CAMERA)) {
if (ProjectUtils.hasPermissionInManifest(getActivity(), PICK_FROM_GALLERY, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
File file = getOutputMediaFile(1);
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
picUri = Uri.fromFile(file);
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_FROM_GALLERY);
}
}
break;
case R.id.cancel_cards:
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
dialog.dismiss();
}
});
break;
}
}
});
you get this exception because the method "getOutputMediaFile" return null and you try to use null object.
first, add null check to file, its always good approach.
second, you have to understand why this method return null and not the file you want.
if you try to use "getExternalStorageDirectory" and call mkdirs(), its depracated, you should use "getExternalFilesDir" on your context/activity.
try to do the change, if it does not help, please share with us the method "getOutputMediaFile" so we can see whats going on there and give you further help.
You have horrible error and null handling. Things go wrong? Sod it, log nothing, do nothing, just return null!
And now you are wondering why you get unexpected null pointer exceptions.
As homer would say, 'Duh'.
We can delve into why it happens here specifically but this is interchangible with a thousand other similar situations. The real fix is for you to stop handling errors like this.
Here's an example:
if (!mediaStorageDir.mkdirs()) {
return null;
}
This is silly. Don't do this. And it would directly lead to your NPE error here if indeed making the directories fails to work.
Log something if you want, but most of all, when things occur that you did not expect, and you don't quite now what it means if it happens, always throw an exception, and add details if you like. The exception means that IF the unexpected happens, at least you get a stack trace with a whole bunch of details and crucially, something pointing right at the place where the weird, unexpected, not quite understood thing happened. It would in this case be pointing right at "Weird, I can't make those dirs" - at least now you know what to investigate. Perhaps your app doesn't have the appropriate file rights, android will just fail the operation if your app doesn't have the user permission.
You pull the same stunt when type isn't 1 - then you just go: Oh, uh, no idea, whatever - just return null. Don't. That return null; in the else block there should be throw new IllegalArgumentException("Type " + type + " not implemented yet"); or whatnot.
Fix those things - and then the answer to your question will become self evident. Without fixing this - we don't know either.
In the below posted code, I am tring to code a utility method and I want to check if an object is null or not and a string is null and not empty.
so, I coded the way shown below with throwing some exception, but I think the code could have been coded in a better way because the way I coded it has nested
try and catch blocks.and i do not think it is a good style
please guide me to better code the belwo method
code:
public static boolean isFragmentShowing(Activity activity, String tag) throws Exception {
try {
if (activity != null) {
FragmentManager fragmentManager = FragmentUtils.getFragmentManagerInstance(activity);
try {
if (tag != null && !tag.equals("")) {
Fragment fragment = fragmentManager.findFragmentByTag(tag);
return (fragment != null && fragment.isVisible())? true : false;
} else {
throw new NullPointerException("isFragmentShowing: fragment tag passed is null or empty");
}
} catch (NullPointerException e) {
Log.e(TAG, "Error: " + e.getMessage().toString());
System.exit(1);
return false;
}
} else {
throw new NullPointerException("isFragmentShowing: context reference is null");
}
} catch (NullPointerException e) {
Log.e(TAG, "Error: " + e.getMessage().toString());
System.exit(1);
return false;
}
}
There are two part of your application. One is request validation and another one is application logic. Separate request validation and application logic. It will be easier to read and maintains. Here is my try in bellow
public static boolean isFragmentShowing(Activity activity, String tag) throws Exception {
//validate request
if(activity == null) {
// throw exception or return value
}
if (tag == null && tag.equals("")){
// throw exception or return value
}
// rest of the part
FragmentManager fragmentManager = FragmentUtils.getFragmentManagerInstance(activity);
Fragment fragment = fragmentManager.findFragmentByTag(tag);
return (fragment != null && fragment.isVisible())? true : false;
}
If all you're going to do with the exception is
Log.e(TAG, "Error: " + e.getMessage().toString());
then you don't need the exception, you just need a string. As I said on your previous question, catching NullPointerException is rarely the correct thing to do; more generally, using exceptions for control flow is a pretty dubious practice. And using System.exit is rarely what you really want to do.
You can create a method something like:
boolean logMessageAndExit(String message) {
Log.e(TAG, "Error: " + message);
System.exit(1);
return false;
}
and then call in your code like this:
if (activity == null) {
return logMessageAndExit("isFragmentShowing: context reference is null");
}
if (tag != null && !tag.equals("")) {
return logMessageAndExit("isFragmentShowing: fragment tag passed is null or empty");
}
Fragment fragment = fragmentManager.findFragmentByTag(tag);
return fragment != null && fragment.isVisible();
Returning a boolean here is a mere convenience to allow you to return it: this convinces the compiler that execution never goes past that line, even though the return is never really executed.
(You could make it return something Throwable instead, so you can throw logMessageAndExit, to make it more clear that it is abnormal).
Alright, here's how your isFragmentShowing method should be like.
You see I've removed ALL of the try/catches. This is because your method already throws a checked Exception and the code calling your static method would need to wrap the call to isFragmentShowing inside the try/catch none the less. You can catch the NPE there quite easily and even print out its stack trace which would let you know which instance was essentially null. Either fragment or activity. The only time we need to actually throw an NPE is when tag.equals("") returns true (since that won't throw an exception). I've also replaced the last ternary operator return by just fragment != null && fragment.isVisible() since it means the same thing (true is returned if the expression evaluates to true and false on the right is returned otherwise, why not the return the result of the expression itself?)
And here's the code:
public static boolean isFragmentShowing(Activity activity, String tag) throws Exception {
FragmentManager fragmentManager = FragmentUtils.getFragmentManagerInstance(activity);
if (tag.equals("")) {
throw new NullPointerException("isFragmentShowing: fragment tag passed is empty");
}
Fragment fragment = fragmentManager.findFragmentByTag(tag);
return fragment != null && fragment.isVisible();
}
I am trying to write a method that will save the maintenance logs for each bike in my app. The method cycles through each bike, which internally cycles through each maintenance log and saves it.
I can see the correct information is there because of the Log.i placed at each point.
The full code for my method -
public static void saveLogs() {
for (Bike thisBike : bikes) {
Log.i("Saving Logs", "" + thisBike);
try {
ArrayList<String> dates = new ArrayList<>();
ArrayList<String> logs = new ArrayList<>();
ArrayList<String> costs = new ArrayList<>();
for (maintenanceLogDetails thisLog : thisBike.maintenanceLogs) {
Log.i("Date :", thisLog.date);
dates.add(thisLog.date);
Log.i("Log :", thisLog.log);
logs.add(thisLog.log);
Log.i("Cost :", Double.toString(thisLog.price));
costs.add(Double.toString(thisLog.price));
}
sharedPreferences.edit().putString("dates", ObjectSerializer.serialize(dates)).apply();
sharedPreferences.edit().putString("logs", ObjectSerializer.serialize(logs)).apply();
sharedPreferences.edit().putString("costs", ObjectSerializer.serialize(costs)).apply();
} catch (Exception e) {
e.printStackTrace();
Log.i("Adding details", "Failed attempt");
}
}
}
At the top of the class I have -
static SharedPreferences sharedPreferences;
The full error I am getting is -
Attempt to invoke interface method 'android.content.SharedPreferences$Editor android.content.SharedPreferences.edit()' on a null object reference
At the line that is -
sharedPreferences.edit().putString("dates", ObjectSerializer.serialize(dates)).apply();
What confuses me, I've pretty much copied the code from somewhere else that works.
What am I doing wrong?
Many thanks!
static SharedPreferences sharedPreferences;
Did you even instantiate it..??
getContext().getSharedPreferences(String, int)
https://developer.android.com/reference/android/content/SharedPreferences.html
https://developer.android.com/reference/android/content/Context.html#getSharedPreferences(java.lang.String,%20int)
I got Activity, in onCreate() I try to fetch data:
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
...............
fillUI();
}
public void getDetailedItem(){
FeedParser parser=new FeedParser();
try{
mItem=parser.parseDetailed();
}catch(Exception e){
closeAndShowError();
}
}
public void fillUI(){
getDetailedItem();
if(mItem!=null){
...............
}else{
closeAndShowError();
}
}
private void closeAndShowError(){
Context context = getApplicationContext();
CharSequence text = getResources().getString(R.string.toast_error);
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
finish();
}
Them problem is, when Exception occures, it is caught, and I expect my activity to finish itself, but I still get code inside fillUI() executed, so I had to put if statement after getDetailedItem();
How do I solve it?
You can do something like this:
public void getDetailedItem(){
FeedParser parser=new FeedParser();
try{
mItem=parser.parseDetailed();
}catch(Exception e){
mItem = null;
}
}
Then in fillUI() if mItem is null you show's error;
You could pass the exception that might get thrown in parseDetailed to the fillUI method:
public void getDetailedItem() throws Exception {
FeedParser parser=new FeedParser();
mItem=parser.parseDetailed();
}
public void fillUI(){
try {
getDetailedItem();
// rest of your code..
} catch(Exception e) {
closeAndShowError();
}
}
The finish() statement is not an immediate return, your code continues to run until it decides it's completed. You need to leave yourself an indicator of the exception, and return up through your call chain when it happens, instead of continuing to run.
Since you are catching the Exception; the fillUI() function is never notified of any error.
Your codepath is as following:
fillUI -> getDetailedItem -> exception caught -> closeAndShowError -> finish() -> return to closeAndShowError -> return to getDetailedItem after caught block -> return back to fillUI.
So basically, the code after getDetailedItem in fillUI is called because you caught the exception and didn't let the other function know. Either by return value, or by throwing (and maybe catching) a new exception.
finish() does cause the Activity to stop as the next step in its lifecycle. But at the point you call it, it's still in the process of another lifecycle step: onCreate(). It will not exit, somehow, immediately in the middle of a method.
That's the answer, but, better would be to redesign your code a bit. This is probably not the cleanest way to handle it if you're dealing with questions like this.
I have an android app which stores information in an SQLite DB. On the activity I can open the Gallery, select a video, and then click on the "Watch Video" button and play that video.
HOWEVER, if I leave that activity and come back later, the saved URI IS in my DB, but loading it through the SAME onclick function produces this Exception error. ANY IDEAS WHY??
public void launchVideo(View view) {
if (my_video != null) {
Uri uri = Uri.parse(my_video);
Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(uri, "video/*");
startActivity(intent);//THROWS ILLEGAL ACTIVITY WHEN WORKING FROM SAVED URI
}
else{...
Using debugger I see the following...
#Override
public void onClick(#NonNull View v) {
if (mResolvedMethod == null) {
resolveMethod(mHostView.getContext());
}
try {
mResolvedMethod.invoke(mResolvedContext, v);
} catch (IllegalAccessException e) {
throw new IllegalStateException(
"Could not execute non-public method for android:onClick", e);
} catch (InvocationTargetException e) {
throw new IllegalStateException(
"Could not execute method for android:onClick", e);
}
}
Similar posts have mentioned issues being the xml or use of methods with the same name. I do not have any methods with the same name and the xml is below for the button:
<Button
android:id="#+id/watchVideo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:onClick="launchVideo"
android:text="#string/watch_my_video"
app:layout_constraintStart_toStartOf="#+id/youtube_link"
app:layout_constraintTop_toBottomOf="#+id/youTubeEditText" />
The URI being passed in both the working and non working case is: "content://com.android.providers.media.documents/document/video%3A595"
Finally in my Debugger I see the following which I take a confirmation everything is public:
mResolvedMethod = {Method#6254} "public void com.android.mybrazilianjiu_jitsudictionary.Controller.AttackDetail.launchVideo(android.view.View)"
accessFlags = 134742017
artMethod = 3966325964
declaringClass = {Class#6043} "class com.android.mybrazilianjiu_jitsudictionary.Controller.AttackDetail"
declaringClassOfOverriddenMethod = {Class#6043} "class com.android.mybrazilianjiu_jitsudictionary.Controller.AttackDetail"
dexMethodIndex = 555
hasRealParameterData = false
parameters = null
override = false
shadow$_klass_ = {Class#3637} "class java.lang.reflect.Method"
shadow$_monitor_ = -2092042593
My latest guess is it is related to:
try {
mResolvedMethod.invoke(mResolvedContext, v);
However, I am just trying to have the video appear in the user's video player via implicit intent which IS what happens until I leave the activity and come back. Note: via checking the database and Debugger the SAME URI is present and being passed to the method in all scenarios.
THANK YOU FOR YOUR INSIGHTS!
By the following, I was able to fix the problem:
IllegalStateException: Could not execute method for android:onClick when trying to migrate to another page? was VERY helpful. On this advice I replaced my Button on click method with the following IN the OnCreate:
Button watchVideoButton = findViewById(R.id.watchVideo);
watchVideoButton.setOnClickListener(new View.OnClickListener() {...
The problem that then surfaced was lack of persistent permissions for the Uri when returning to the activity.
Persistent permission was taken via the following:
getContentResolver().takePersistableUriPermission(uri, FLAG_GRANT_READ_URI_PERMISSION);
...which I placed BEFORE the onCreate in:
androidx.activity.result.ActivityResultLauncher<String> mGetContent = registerForActivityResult(new ActivityResultContracts.GetContent(),
new ActivityResultCallback<Uri>() {
#Override
public void onActivityResult(Uri uri) {
my_video = uri.toString();
getContentResolver().takePersistableUriPermission(uri, FLAG_GRANT_READ_URI_PERMISSION);
Move move;
move = new Move(MoveID,PositionTableID, MoveName, MoveStatus, GiY,AttackY, DefenseY, Description, internetVideoLink, my_video);
myJiuJitsuDictionaryRepository.insert(move);
}
});