Android 11: Tried to access UI constants from a non-visual Context - java

I was running project OnmiNotes on Github when I ran, and looking at Logcat, the result was an error: "Tried to access UI constants from a non-visual Context", I found out that this is a new error on android 11, and there are quite a few suggestions to correct this error on gg, I look at them, those cases are not suitable for my case. And the person who wrote this app wrote on android 8, so they probably didn't know this error. Below are the code lines I find relevant.
There is an error in Logcat:
Tried to access UI constants from a non-visual
Context:it.feio.android.omninotes.OmniNotes#e9ea0eUI constants, such as
display metrics or window metrics, must be accessed from Activity or
other visual Context. Use an Activity or a Context created with
Context#createWindowContext(int, Bundle), which are adjusted to the
configuration and visual bounds of an area on screen
and:
Tried to access visual service WindowManager from a non-visual Context:it.feio.android.omninotes.OmniNotes#e9ea0e Visual services, such as WindowManager, WallpaperService or LayoutInflater should be accessed from Activity or other visual Context. Use an Activity or a Context created with Context#createWindowContext(int, Bundle), which are adjusted to the configuration and visual bounds of an area on screen.
And there are two command lines I see mentioned in logcat error
1.In BaseActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
// Forces menu overflow icon
try {
ViewConfiguration config = ViewConfiguration.get(this.getApplicationContext()); //ERROR IN LOGCAT IN THIS LINE
#SuppressLint("SoonBlockedPrivateApi") Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
if (menuKeyField != null) {
menuKeyField.setAccessible(true);
menuKeyField.setBoolean(config, false);
}
} catch (Exception e) {
LogDelegate.w("Just a little issue in physical menu button management", e);
}
super.onCreate(savedInstanceState);
}
MainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);//ERROR IN LOGCAT IN THIS LINE
setTheme(R.style.OmniNotesTheme_ApiSpec);
binding = ActivityMainBinding.inflate(getLayoutInflater());
View view = binding.getRoot();
setContentView(view);
EventBus.getDefault().register(this);
Prefs.getPreferences().registerOnSharedPreferenceChangeListener(this);
initUI();
if (IntroActivity.mustRun()) {
startActivity(new Intent(getApplicationContext(), IntroActivity.class));
}
}
Does anyone know how to deal with it? Any help will be appreciated.

Replace this.getApplicationContext() and getApplicationContext() with this. this appears to be an Activity in both places.

Related

The value of QR Code Scanner cannot show on new activity

I am trying to make a simple QR Code scanner and run well if the result shows in the MainActivity. But when I'm trying to generate new Activity as a result, it can't show. Would you like to help me with this problem? Thank you.
Here is the result of the scanner code in the scanner.java:
#Override
public void handleResult(Result rawResult) {
startActivity(new Intent(getApplicationContext(),ResultActivity.class));
ResultActivity.scanText2.setText(rawResult.getText());
onBackPressed();
}
And here is the code of my new Activity for showing the result:
public class ResultActivity extends AppCompatActivity {
public static TextView scanText2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_patient);
scanText2 = (TextView) findViewById(R.id.scanText2);
}
}
There are a lot of issues with this:
You are launching PatientActivity, not ResultActivity in handleResult()
You are trying to set the value of a TextView in another Activity with this code:
ResultActivity.scanText2.setText(rawResult.getText());
This is an absolute no-no. Pass the data to ResultActivity as an Intent extra when you launch it. You cannot access the views of another Activity like that.
You expect that ResultActivity.scanText2 will contain a reference to a TextView, but at this point it will only contain null. The reason is that it takes some time for ResultActivity to actually start and call its onCreate(). You have not accounted for this timing in your code. To solve this problem, just see (2) above.
Also, you should have gotten a bunch of crashes with useful messages in your logcat. In the future please look there to solve problems and/or post the messages with stacktrace in your Stackoverflow questions.

Android use two classes for a single layout

I'm trying to separate some of my java in a few different files.
I have my main class:
public class StartPage extends Activity {
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start_page);
}
...
}
And then I have this other class that I'd like to run on the same layout:
public class part_settings_session extends Activity {
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start_page);
Toast.makeText(getApplicationContext(), "This is from settings", Toast.LENGTH_SHORT).show();
}
...
}
But I'm not able to see that Toast happen anywhere or at any time. Is there a way to make both of these classes work in two separate files? This is to organize scripts for my own sake.
Two Activities can not be visible at same time and here in your code you have defined two Activities with same layout. Your code is fine but to see both activities working, you have to manually start next activity. Below code will help you. This code will start Next Activity 3 seconds after loading First Activity.
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
startActivity(new Intent(StartPage.this, NextPage.class));
finish();
}
}, 3000);
in your onCreate() for the 2nd class, put a Log.d("part_settings_session", "onCreate"); and see if the onCreate ever gets called in the first place. (Since they are using the same layout, it might be difficult to see if you are 'actually' creating an instance of THIS class.
My guess is that you might not even be creating an instance of the part_settings_session class. And without logging it is pretty hard to tell that.
Here is a nice Activity base class that will log all life-cycle events for you
https://github.com/douglascraigschmidt/CS282/blob/c5cf5c4808ea082988ab87c00eeade4837eac967/assignments/assignment1/src/edu/vandy/common/LifecycleLoggingActivity.java

Android Wear append to textView crashes app

So i have a strange issue when trying to retrieve a list of sensors on my application.
Printing to the log works just fine.
When I try to append to a textView, it crashes.
Here is where I am doing the attempted appending:
protected void onCreate(Bundle b) {
super.onCreate(b);
setContentView(R.layout.activity_main);
sensorTextView = (TextView) findViewById(R.id.sensorList);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
initialiseAccelerometer();
sensorManager=(SensorManager) getSystemService(SENSOR_SERVICE);
List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
for (Sensor sensor : sensors) {
Log.d("Sensors", "" + sensor.getName());
sensorTextView.append(sensor.getName());
}
sensorManager.registerListener(
this,
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_NORMAL);
mGestureDetector = new GestureDetectorCompat(this, new LongPressListener());
}
And subsequent error:
java.lang.RuntimeException: Unable to start activity
ComponentInfo{com.example.XXXXXX.XXXXXXXXXXX.MainActivity}:
java.lang.NullPointerException:
Attempt to invoke virtual method
'void android.widget.TextView.append(java.lang.CharSequence)' on a null object reference
And the XML file with correct id:
android:id="#+id/sensorList"
Can anyone point me in the right direction or advise me as to what I'm doing wrong?
activity_main.xml:
<android.support.wearable.view.WatchViewStub
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/watch_view_stub"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:rectLayout="#layout/rect_activity_main"
app:roundLayout="#layout/round_activity_main"
tools:context=".MainActivity"
tools:deviceIds="wear"></android.support.wearable.view.WatchViewStub>
Thanks,
Emmett
This section of the documentation notes some quirks of WatchViewStub. In particular, note the following:
The layouts that you specify for square or round screens are not inflated until WatchViewStub detects the shape of the screen, so your app cannot access their views immediately. To access these views, set a listener in your activity to be notified when the shape-specific layout has been inflated
You are probably trying to set the TextView reference too early, which is why it's null at the point you attempt to append text. If you instead use an OnLayoutInflatedListener as in the sample code below (also from the documentation) to wait until the appropriate round/square layout is inflated, you should find that the reference is initialized properly for both screen types:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_wear);
WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
#Override public void onLayoutInflated(WatchViewStub stub) {
// Now you can access your views
TextView tv = (TextView) stub.findViewById(R.id.text);
...
}
});
}
[Note that a colleague of mine has indicated that there is currently a bug that requires you to define the square layout xml attribute and the round layout xml attribute in a specific order for this to work - I don't remember offhand which needs to be first, just a heads-up if you run into problems].

Android Trying to display a welcome fragment when app starts, but not after

I've been looking for a way to have the blank detail side of my fragment layout host a welcome screen (or something - login perhaps) on start up. Afterwards, when a user presses one of the left side menu items, I'd like to eliminate the fragment for the remainder of the program run. I don't want to add it to the backstack, as that messes up my configuration changes. I've considered using shared prefs to host a boolean about whether the fragment has been displayed. The only concern with this method is where to safely reset the boolean value for the next run of the app. I'm of the impression that there's no gaurantee that the onStop, onDetach etc. will definitely get called upon closing of the app, so if the app got closed in the wrong state, it would be rendered useless ( the first fragment wouldn't display - crash )
Anyone have any ideas on how I could implement a filler for the right side of the app upon startup?
I've been trying to add something to the onCreate of my main activity thus far with no success.
Thanks in advance.
Ken
If your fragment can be part of its own Activity, you can use the android:noHistory="true" attribute to keep the Activity off of the backstack. If your user tries to navigate backwards, it'll hit the bottom of the backstack twice before exiting your application.
If you can't split your fragment into its own activity, noHistory may not work -- I can't say as I haven't tried it myself.
I was able to come up with a solution to creating a welcome or login screen which will display both fragments and activities from the main activity. Seems to be working fine as tested.
private boolean welcomeShown;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_list);
if (findViewById(R.id.item_detail_container) != null) {
mTwoPane = true;
((MainFragment) getSupportFragmentManager().findFragmentById(
R.id.item_list)).setActivateOnItemClick(true);
}
if (savedInstanceState != null){
welcomeShown = savedInstanceState.getBoolean("displayed");
}
if(!welcomeShown){
if (mTwoPane){
WelcomeFragment welcomeFragment = new WelcomeFragment();
getSupportFragmentManager().beginTransaction()
.add(R.id.item_detail_container, welcomeFragment)
.commit();
}
else{
Intent welcomeIntent = new Intent(this, WelcomeActivity.class);
startActivity(welcomeIntent);
welcomeShown = true;
}
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean("displayed", true);
}

Custom AlertDialog fails to initialize in onCreate()

I'm trying to build a custom AlertDialog by extending the AlertDialog class.
As usual, I'm setting up the dialog inside its onCreate() method. Or, I'm trying to do so:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setTitle("Some title");
this.setButton(BUTTON_POSITIVE, "Click me", (DialogInterface.OnClickListener)null);
final FrameLayout custom = (FrameLayout) this
.findViewById(android.R.id.custom);
custom.addView(this.getLayoutInflater().inflate(R.layout.mydlg, null),
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
}
Now, when it comes to displaying an instance of this dialog, nothing is shown. The current Activity fades out and loses focus but not a single pixel of my dialog is displayed. Pressing Back brings the Activity back to the foreground, indicating to me that a dialog actually is shown, but just a completely empty one.
However, when I create an AlertDialog and use, for instance, dlg.setButton(BUTTON_POSITIVE, "Click me", (DialogInterface.OnClickListener)null);
the dialog is shown with the respective button.
Even when I set up my custom dialog in its constructor using the very same code as above everything seems to work ok.
Now, how can this be? Why can't I seem to initialize my dialog in its onCreate() method? Isn't this the way you're supposed to initialize any GUI element? What am I missing?
EDIT
Please note, that something is 'shown', fading out the Activity and taking focus from it. It's just that it seems to be completely empty/invisible.
Here another attempt:
this.setTitle("Some title");
this.setButton(BUTTON_POSITIVE, "Click me", (DialogInterface.OnClickListener)null);
final View v = this.getLayoutInflater().inflate(R.layout.mydlg, null);
this.setView(v);
These exact lines do work when put into my dialog's constructor.
These exact lines do not work when put into my dialog's onCreate().
What is going on here?!
Generally, am I not supposed to do it in onCreate()? - Am I facing trouble if I resort to doing the above initialization in the constructor instead? (This does not seem too clean to me, anyway.)
You need to call the show() method in order to see something.
You should consider using AlertDialog.Builder instead of subclassing AlertDialog itself. It allows you to do all the things you need in your example (in order: setTitle(),setPositiveButton() and setView() ). Don't forget to call create() at the end to actually get your dialog.
Also, check if your onCreateDialog() and onPrepareDialog() activity methods are implemented correctly. If you don't have them implemented at all (an unmanaged dialog), consider doing that anyway, especially if your app allows for orientation changes. You probably know about this, but here is a tutorial:
http://developer.android.com/guide/topics/ui/dialogs.html
also, DialogFragments are a bit easier way to implement this, but you need a newer API version or the Compatibility package:
http://developer.android.com/reference/android/app/DialogFragment.
One final issue - where are you calling show() in your activity? onResume() should be OK, onCreate() not as much.
Sorry I'm late to the party :)
You have to thing differently for the alert dialog.
The way I did it is to customize the view before creating the alert dialog:
// This is the activity that is the background of the AlertDialog
public class Main extends Activity {
public static final int DIALOG_CONFIG = 1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.emptybackground);
}
#Override
protected void onStart() {
super.onStart();
// Open the alert dialog on openning the Activity
showDialog(Main.DIALOG_CONFIG );
}
protected Dialog onCreateDialog(int id) {
LayoutInflater factory = LayoutInflater.from(this);
switch (id) {
case DIALOG_CONFIG:
// Here, we load the existing view R.layout.config
configView = factory.inflate(R.layout.config, null);
configDialog = new AlertDialog.Builder(this)
.setTitle("Configuration")
.setView(configView)
.create();
// Using configView, you can do whatever you want with the view. Here, we add value to a spinner.
Spinner spinner = (Spinner)configView.findViewById(R.id.config_select_conn);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
adapter.add("TCP");
adapter.add("Bluetooth");
spinner.setAdapter(adapter);
return configPrinter;
}
return null;
}
}
you should call custom_alertDialog.create(); before custom_alertDialog.show();

Categories