How to import AlertDialog in Kotlin? - android-studio

I tried to google my problem but I couldn't found it, that's why I ask.
Error: unresolved reference: AlertDialog
Question: How to import AlertDialog because if I google it then I see different methods that causing the error above, e.g. import android.app.AlertDialog or import androidx.appcompat.app.AlertDialog or something else, I need something universal that will never break. I'm wondering why the #include <...> in C++ never get expired and lasts for many years.
Import from https://geeksforgeeks.org/how-to-create-a-custom-yes-no-dialog-in-android-with-kotlin/
import android.app.AlertDialog
Import from https://www.geeksforgeeks.org/how-to-create-an-alert-dialog-box-in-android/
import androidx.appcompat.app.AlertDialog;
Import from https://www.digitalocean.com/community/tutorials/android-alert-dialog-using-kotlin
import android.support.v7.app.AlertDialog;
Code in "MainActivity.kt" (Kotlin with C++ in Android Studio Dolphin | 2021.3.1 Patch 1)
package com.emcengine.emceditor
import android.app.NativeActivity
import android.os.Bundle
import android.content.Context
import android.view.inputmethod.InputMethodManager
import android.view.KeyEvent
import java.util.concurrent.LinkedBlockingQueue
//_/--------------------------------------------------\_
import android.app.AlertDialog // error: unresolved reference: AlertDialog
// \--------------------------------------------------/
class MainActivity : NativeActivity() {
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
fun showSoftInput() {
val inputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.showSoftInput(this.window.decorView, 0)
}
fun hideSoftInput() {
val inputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.hideSoftInputFromWindow(this.window.decorView.windowToken, 0)
}
// Queue for the Unicode characters to be polled from native code (via pollUnicodeChar())
private var unicodeCharacterQueue: LinkedBlockingQueue<Int> = LinkedBlockingQueue()
// We assume dispatchKeyEvent() of the NativeActivity is actually called for every
// KeyEvent and not consumed by any View before it reaches here
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
if (event.action == KeyEvent.ACTION_DOWN) {
unicodeCharacterQueue.offer(event.getUnicodeChar(event.metaState))
}
return super.dispatchKeyEvent(event)
}
fun pollUnicodeChar(): Int {
return unicodeCharacterQueue.poll() ?: 0
}
//_/--------------------------------------------------\_
fun messageBox() {
AlertDialog.Builder builder // error: unresolved reference: AlertDialog
//builder = new AlertDialog.Builder(this)
}
// \--------------------------------------------------/
}

In general: You don't have to add the imports by hand. AndroidStudio does all that for you when you just reference another class etc. Try it by removing the import and simply typing AlertDialog somewhere. Then select it from the list of suggestions in the dropdown.
The one you are probably looking for is import androidx.appcompat.app.AlertDialog.
Also, in Kotlin the type stands after the variable name (and is optional in that case):
val builder: AlertDialog = AlertDialog.Builder(context)

import android.app.AlertDialog
Old AlertDialog class, shouldn't be used anymore. Still there for retrocompatibility purposes.
import android.support.v7.app.AlertDialog
AlertDialog that works on both old and new Android versions while supporting the new API. This requires a new dependency on the support v7 library.
import androidx.appcompat.app.AlertDialog
Android X (aka new SDK) AlertDialog. This is the one you want to use.
More on this

This is an important thing to know if you're doing Android development: there are a whole lot of versions of Android out there, because many devices stop getting updates after only a few years. That means new Android features, and updates and fixes for old features, just don't exist on a lot of devices.
That's a problem when you're trying to write software that works on all those devices - some stuff just won't be available. Some stuff will work differently, or display differently. Some stuff will have bugs that were fixed in later versions, and you'll have to work around those.
At best, you'll have to do a lot of if the API version is between this and this checks, with different code paths for different versions. At worst, some things won't be available at all, and you'll have to decide between not using those features, locking your app to the range of devices where it is available, or effectively making multiple versions of your app. And then you have to test it all too!
So what some very nice people at Android produced is the Support Library. This basically backports features and fixes so they're available on older devices, instead of only being able to use the stuff baked into the version of the OS they have. It also gives you a common interface for those features - you don't need to use a Compat library for old APIs and the system version for newer ones, you just use the Compat version and that's it. It'll work out what to do internally, you don't need to worry about it.
They also test all these features, so you can assume they Just Work on every API - you don't need to do special testing to see if your own workarounds are being handled correctly, someone's already done that for the Support Library implementations!
So it's recommended standard practice to always use the Support Library in your Android projects, and always use its implementation for things over the standard library ones. That's why your Activities inherit from AppCompatActivity and not Activity, and why the Fragment class that gets automatically imported is the androidx one, and not the standard Fragment (which was actually deprecated several versions ago)
As for your imports, the trouble is you're reading tutorials and guides that are years apart, and things change. m0skit0's answer explains what each version is - but basically the support library is deprecated, and you want the new AndroidX/Jetpack versions of things.
AndroidX is a little different, instead of one big support library (which got broken into a handful of still big support libraries by API version) it's much more granular. That means you have to install the specific libraries you want. AlertDialog (and the Material Design version) are part of the androidx.appcompat:appcompat library (top of the page, or in the package name) - so you need to add that as a dependency, and that's the import you'll use in your app.

Related

How can I know the retained class name or keyword when I use navigation framework in Android Studio?

The following code is from the project at https://github.com/mycwcgr/camera/tree/master/CameraXBasic
The project use the latest navigation framework, I find there are some retained class name such as CameraFragmentDirections, GalleryFragmentArgs.
The system have no prompt information for these class name, must I remember these keywords by myself?
Code
/** Method used to re-draw the camera UI controls, called every time configuration changes */
#SuppressLint("RestrictedApi")
private fun updateCameraUi() {
// Listener for button used to view last photo
controls.findViewById<ImageButton>(R.id.photo_view_button).setOnClickListener {
Navigation.findNavController(requireActivity(), R.id.fragment_container).navigate(
CameraFragmentDirections.actionCameraToGallery(outputDirectory.absolutePath))
}
}
/** Fragment used to present the user with a gallery of photos taken */
class GalleryFragment internal constructor() : Fragment() {
/** AndroidX navigation arguments */
private val args: GalleryFragmentArgs by navArgs()
}
No you do not need to remember these things by yourself, if you know of a trick.
For example, if you don't remember the "keyword" Directions, but you know you want to do something related to CameraFragment, you can start typing e.g. CameraFragm in Android Studio. It will then suggest CameraFragment and CameraFragmentDirections for you. That way you can find CameraFragmentDirections easily even though you did not remember the keyword Directions.
There are not that many keywords to worry about though. After working with the Navigation framework for a while, you will remember them all.
If you are curious, you can find the generated classes here after a build:
./app/build/generated/source/navigation-args/...
e.g. after a debug build:
./app/build/generated/source/navigation-args/debug/com/android/example/cameraxbasic/fragments/CameraFragmentDirections.java
If you are even more curious, the code that generates these classes is here:
https://android.googlesource.com/platform/frameworks/support/+/refs/heads/androidx-master-dev/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/java/JavaNavWriter.kt
There you can for example find this code:
internal fun Destination.toClassName(): ClassName {
val destName = name ?: throw IllegalStateException("Destination with actions must have name")
return ClassName.get(destName.packageName(), "${destName.simpleName()}Directions")
}
which is the code that decides what name CameraFragmentDirections gets. (Note "${destName.simpleName()}Directions" at the end.)

accessing Android native method from different project

I am working on an Android application that will call a .so file created by a different Android NDK application.
I have created the following folder structure in my project and copied over the .so files as seen below:
|--app:
|--|--src:
|--|--|--main
|--|--|--|--jniLibs
|--|--|--|--|--armeabi
|--|--|--|--|--|--libmylib.so
|--|--|--|--|--x86
|--|--|--|--|--|--libmylib.so
I call this library through my application via the following code:
static {
System.loadLibrary("mylib");
}
I then call the method from this shared object via the following code:
String str = stringFromJNI();
This does not work as the program looks for mangled function name as follows:
com.example.androidlibcall.MainActivity.stringFromJNI() where my .so function will be using a different package name and hence a different function name is generated.
I am not really sure what I need to do to call the functions from the external library, I assume I can create my own library and utilize dlopen() to load the external library and make calls to it, but was wondering if there are the other methods to achieve this or not.
My ultimate goal is to be able to create applications that can call pre-existing libraries that are on the mobile device, but since I am new to NDK/Android I am not sure what is the best method for this and have not found good examples to work with.
A lot of the pre-existing similar questions seem to be dealing with older versions of Android Studio that don't seem applicable anymore.
I am using the latest version of Android Studio (3.1.2) with Gradle 4.4 on Windows 7 machine.
Please advise.
Thanks!
Generally speaking, it's not a good idea to have native methods in application's MainActivity, but this should not worry us now that we are forging a workaround.
Assume that your new project has com.example.other.MainActivity.java, and you want to call the native method com.example.androidlibcall.MainActivity.stringFromJNI() from com.example.other.MainActivity.onCreate(). To do this, create a new Java class in your other app:
package com.example.androidlibcall;
public class MainActivity {
public static native String stringFromJNI();
}
and in your existing MainActivity class,
package com.example.other;
import static com.example.androidlibcall.MainActivity.stringFromJNI;
class MainActivity {
static {
System.loadLibrary("mylib");
}
}
public class MainActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
…
String qq = stringFromJNI();
…
}
}
You see that com/example/androidlibcall/MainActivity.java contains no logic, no data, no code. It is only a wrapper that lets us easily use libmylib.so without rebuilding it.

Observable.fromPromise does not exist ONLY when building on CircleCI

Can anybody please help me figuring this out. The code fragment below runs in a NodeJS Typescript environment en this works fine on multiple machines across multiple platforms but fails to build on CircleCI with the following:
error TS2339: Property 'fromPromise' does not exist on type 'typeof Observable'.
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/frompromise';
import 'rxjs/add/operator/do';
return Observable.fromPromise(col.insertOne(document))
What is different in the CircleCI environment that causes this and what would be a solution?
With RxJS 5.5+, the Observable prototype does not include any static methods. For this reason, you will need to take one of two approaches to include the fromPromise (and other) static methods.
RxJS v5.5.2 is the default dependency version for Angular 5.
Approach 1 (preferred option)
To use the fromPromise method, independently import it from rxjs/observable.
import { fromPromise } from 'rxjs/observable/fromPromise';
let observable = fromPromise(promise);
This approach is beneficial for reducing the bundle size, as it will import only what you need by patching the Observable prototype.
Approach 2 (unoptimized approach)
To use the static Observable.fromPromise as you previously have, you will need to import Observable from rxjs/Rx.
import Rx from 'rxjs/Rx';
This method will import the entire core set of functionality, resulting in a larger bundle size.
OK, it must not be my day. The problem was the capital 'P' in the import statement.
import 'rxjs/add/observable/fromPromise';
This is no problem on platforms with a case insensitive filesystem so I didn't notice it on Mac OS/X and also not on Windows. but CircleCI uses Linux.

SearchDomainFactory.Instance is obsolete: 'Inject me!' ( Can't find out how to create instance)

I'm in the process of trying to migrate a R# extension project from R# 6 to R# 8. (I've taken over a project that someone wrote, and I'm new to writing extensions.)
In the existing v6 project there is a class that derives from RenameWorkflow, and the constructor used to look like this;
public class RenameStepWorkflow : RenameWorkflow
{
public RenameStepWorkflow(ISolution Solution, string ActionId)
: base(Solution, ActionId)
{
}
This used to work in R# SDK v 6, but now in V8, RenameWorkflow no longer has a constructor that takes Solution and actionId. The new constructor signature now looks like this;
public RenameWorkflow(
IShellLocks locks,
SearchDomainFactory searchDomainFactory,
RenameRefactoringService renameRefactoringService,
ISolution solution,
string actionId);
now heres my problem that I need help with (I think)
I've copied the constructor, and now the constructor of this class has to satisfy these new dependancies. Through some digging I've managed to find a way to satisfy all the dependencies, except for 'SearchDomainFactory'. The closest I can come to instantiating via the updated constructor is as follows;
new RenameStepWorkflow(Solution.Locks, JetBrains.ReSharper.Psi.Search.SearchDomainFactory.Instance, RenameRefactoringService.Instance, this.Solution, null)
All looks good, except that JetBrains.ReSharper.Psi.Search.SearchDomainFactory.Instance is marked as Obsolete, and gives me a compile error that I cannot work around, even using #pragma does not allow me to compile the code. The exact error message I get when I compile is Error 16 'JetBrains.ReSharper.Psi.Search.SearchDomainFactory.Instance' is obsolete: 'Inject me!'
Obvious next question..ok, how? How do I 'inject you'? I cannot find any documentation over this new breaking change, in fact, I cannot find any documentation (or sample projects) that even mentions DrivenRefactoringWorkflow or RenameWorkflow, (the classes that now require the new SearchDomainFactory), or any information on SearchDomainFactory.Instance suddenly now obsolete and how to satisfy the need to 'inject' it.
Any help would be most appreciated! Thank you,
regards
Alan
ReSharper has its own IoC container, which is responsible for creating instances of classes, and "injecting" dependencies as constructor parameters. Classes marked with attributes such as [ShellComponent] or [SolutionComponent] are handled by the container, created when the application starts or a solution is loaded, respectively.
Dependencies should be injected as constructor parameters, rather than using methods like GetComponent<TDependency> or static Instance properties, as this allows the container to control dependency lifetime, and ensure you're depending on appropriate components, and not creating leaks - a shell component cannot depend on a solution component for instance, it won't exist when the shell component is being created.
ReSharper introduced the IoC container a few releases ago, and a large proportion of the codebase has been updated to use it correctly, but there are a few hold-outs, where things are still done in a less than ideal manner - static Instance properties and calls to GetComponent. This is what you've encountered. You should be able to get an instance of SearchDomainFactory by putting it as a constructor parameter in your component.
You can find out more about the Component Model (the IoC container and related functionality) in the devguide: https://www.jetbrains.com/resharper/devguide/Platform/ComponentModel.html

JBehave - all steps marked pending?

I'm trying to create and run a simple JUnitStory to run a .story file.
I have this:
class Scenario1 extends JUnitStory {
#Delegate MySteps steps = new MySteps()
#Override
public Configuration configuration() {
return new MostUsefulConfiguration()
.useStoryLoader(new LoadFromRelativeFile(new File('src/test/groovy').toURL()))
.useStoryReporterBuilder(
new StoryReporterBuilder()
.withDefaultFormats()
.withFormats(Format.HTML, Format.CONSOLE, Format.TXT)
);
}
#Override
public List candidateSteps() {
final candidateSteps = new InstanceStepsFactory(configuration(), this).createCandidateSteps()
return candidateSteps;
}
}
With or without the delegate (copying and pasting in all the annotated methods of MySteps), whenever I run JBehave, I get the following output:
somePattern(){
// PENDING
}
It's like the individual stories don't pick up the steps.
When I create a "Stories" class and pull all the story files in with storyPaths, the individual steps are defined. Using a debugger, I see that candidateSteps is being hit, but it's not pulling in the data it needs to.
What could possibly be going on here?
You don't need to delegate to the Steps. And also you should not override candidateSteps, but rather stepsFactory. In later versions of JBehave, candidateSteps is deprecated, to make that preference for the factory method more prominent ( http://jbehave.org/reference/stable/javadoc/core/org/jbehave/core/ConfigurableEmbedder.html#candidateSteps() )
See this blog, where I explained how the basic JBehave configuration works in more detail:
http://blog.codecentric.de/en/2012/06/jbehave-configuration-tutorial/
Andreas
Here is your answer buddy:
The package of format has Changed.
This is the deprecated
import static org.jbehave.core.reporters.StoryReporterBuilder.Format.HTML;
This is the new one :)
import static org.jbehave.core.reporters.Format.HTML;
Took a while to find the answer, but was hidden on the jbehave documentation
Hope it helps!
Cheers!
You shouldn't need to use the #Delegate - your JUnitStory is not your Steps class. Can you try passing in steps where you have this?
When you pass in a class that has been bytecode manipulated for Steps classes, JBehave may not see the jbehave annotations anymore.
JBehave is old, underdeveloped technology. Don't use it.

Resources