I´m traying to create app in Android studio thank this app connect to my hosting server and to do any operation with the data.
I have a button that instanciate a kotlin class that contain method to connect DB and function to do operation.
My problem it´s that when i do click in my button my function connect return this message:
I/System.out: java.sql.SQLNonTransientConnectionException: Could not create connection to database server.
i´m using JDBC Driver to connect to my DB, in the future i do a web service to do this.
My function connect have this:
class MySQLDatabaseConnector {
internal var conn: Connection? = null
internal var username = "root" // provide the username
internal var password = "" // provide the corresponding password
fun connect() {
val JDBC_DRIVER = "com.mysql.jdbc.Driver"
val DB_URL = "jdbc:mysql://192.167.1.108:3308/prueba"
val USER = "root"
val PASSWORD = ""
try {
Class.forName(JDBC_DRIVER).newInstance()
conn = DriverManager.getConnection(DB_URL, USER, PASSWORD)
/*ar stmt = conn!!.createStatement()
var resultSet = stmt.executeQuery("SELECT * FROM users")
while(resultSet.next()){
var record = resultSet.getString(1) + " " + resultSet.getString(2) + "\n"
println(record)
}
println(stmt)*/
} catch (ex: SQLException) {
// handle any errors
println(ex.toString())
} catch (ex: Exception) {
// handle any errors
println(ex.toString())
}
}
and my activity main its:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login);
val buttonLogin = findViewById(R.id.btLogin) as Button
buttonLogin.setOnClickListener{
val connect = MySQLDatabaseConnector()
connect.connect()
}
}
i have my connector in lib:
mysql-connector-java-8.0.27.jar
i´m using this. I dowloaded it from this URL with software for windows:
https://dev.mysql.com/downloads/connector/j/5.1.html
i hope that anybody can help me.
Thanks you for readme and sorry for my english
Related
TLDR: I am looking for a way to expose a POST endpoint from an Android app. Is this possible? If so, how?
Long story:
I want to receive data from Arduino devices on my android app. So I want a way to get this data through Wi-Fi (that may be a wrong assumption) but without internet connection. My current idea is to post the data from the Arduino to the smartphone over Wi-Fi.
The thing I don't know, and I didn't find answer yet is: Can I get data send to my hotspot Wi-Fi inside my app?
To host endpoints inside your Android application you will need a sever to serve those endpoints. You can use the NanoHttpD for this.
Check this question to check how to use NanoHttpD in Android.
Thank you to both #CommonsWare and #Taranmeet Singh for helping to find my solution.
I build a small http server on my phone that can be reach through http call from my laptop.
Two points were not so obvious for me :
the tecno
the host ip
For the first point, you can use :
NanoHttpD
AsuncHttpServer ex :
https://github.com/andreivisan/AndroidAsyncHttpServer/blob/master/app/src/main/java/server/http/android/MainActivity.java
Sun http :
https://medium.com/hacktive-devs/creating-a-local-http-server-on-android-49831fbad9ca
Ktor :
https://diamantidis.github.io/2019/11/10/running-an-http-server-on-an-android-app
I choose the last option because :
It used natively kotlin
It is build and maintained by JetBrains, the other library were less maintained
It is really light (10 lines to make it works)
To use Ktor you need to add this in your app gradle :
defaultConfig {
...
multiDexEnabled true
}
For the second point : by default you are bind and localhost, but you can change that :
embeddedServer(Netty, host = "192.168.43.1", port = 8080)
This ip is the default one for Android (it seems), you can also Utils method to get it :
How to get IP address of the device from code?
fun getIPAddress(useIPv4: Boolean): String {
try {
val interfaces: List<NetworkInterface> =
Collections.list(NetworkInterface.getNetworkInterfaces())
for (intf in interfaces) {
val addrs: List<InetAddress> = Collections.list(intf.inetAddresses)
for (addr in addrs) {
if (!addr.isLoopbackAddress) {
val sAddr = addr.hostAddress
//boolean isIPv4 = InetAddressUtils.isIPv4Address(sAddr);
val isIPv4 = sAddr.indexOf(':') < 0
if (useIPv4) {
if (isIPv4) return sAddr
} else {
if (!isIPv4) {
val delim = sAddr.indexOf('%') // drop ip6 zone suffix
return if (delim < 0) sAddr.toUpperCase(Locale.ROOT) else sAddr.substring(
0,
delim
).toUpperCase(Locale.ROOT)
}
}
}
}
}
} catch (ignored: Exception) {
} // for now eat exceptions
return ""
}
This work for me, hope it will help others.
Final code look like this:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
embeddedServer(Netty, host = getIPAddress(true), port = 8080) {
install(ContentNegotiation) {
gson {}
}
routing {
get("/") {
call.respond(mapOf("message" to "Hello , this ktor server"))
}
}
}.start(wait = false)
}
/**
* Get IP address from first non-localhost interface
*
* #param useIPv4 true=return ipv4, false=return ipv6
* #return address or empty string
*/
private fun getIPAddress(useIPv4: Boolean): String {
try {
val interfaces: List<NetworkInterface> =
Collections.list(NetworkInterface.getNetworkInterfaces())
for (intf in interfaces) {
val addrs: List<InetAddress> = Collections.list(intf.inetAddresses)
for (addr in addrs) {
if (!addr.isLoopbackAddress) {
val sAddr = addr.hostAddress
//boolean isIPv4 = InetAddressUtils.isIPv4Address(sAddr);
val isIPv4 = sAddr.indexOf(':') < 0
if (useIPv4) {
if (isIPv4) return sAddr
} else {
if (!isIPv4) {
val delim = sAddr.indexOf('%') // drop ip6 zone suffix
return if (delim < 0) sAddr.toUpperCase(Locale.ROOT) else sAddr.substring(
0,
delim
).toUpperCase(Locale.ROOT)
}
}
}
}
}
} catch (ignored: Exception) {
} // for now eat exceptions
return ""
}}
I am using TheMovieDB API to call the JSON Response of the popular movies and put it into a ScrollView. I have ensured that I have done all the neccessary steps to get the API. However it does not work and does not display anything. If I use another API: "https://jsonplaceholder.typicode.com/posts", it works and the JSON data is displayed into the ScrollView.
Network Utils:
companion object {
private val TAG: String = NetworkUtils::class.java!!.simpleName
private val JSON_RESPONSE_URL = "https://api.themoviedb.org/3/movie/popular?api_key=myapikeyishere"
private val TYPE_SINGLE = 1
private val TYPE_ALL = 0
/**
* Builds the URL used to talk to the weather server using a location. This location is based
* on the query capabilities of the weather provider that we are using.
*
* #param locationQuery The location that will be queried for.
* #return The URL to use to query the weather server.
*/
fun buildURLSingleType(id: Int): URL {
return buildUrl(
TYPE_SINGLE,
id
)
}
fun buildURLAll(): URL {
return buildUrl(
TYPE_ALL,
0
)
}
private fun buildUrl(type: Int, id: Int): URL {
var uri = Uri.parse(JSON_RESPONSE_URL).buildUpon()
if (type == TYPE_SINGLE) {
uri.appendPath("1").build()
}
val builtUri = uri.build()
var url: URL? = null
try {
url = URL(builtUri.toString())
} catch (e: MalformedURLException) {
e.printStackTrace()
}
Log.v(TAG, "Built URI " + url!!)
return url
}
/**
* This method returns the entire result from the HTTP response.
*
* #param url The URL to fetch the HTTP response from.
* #return The contents of the HTTP response.
* #throws IOException Related to network and stream reading
*/
#Throws(IOException::class)
fun getResponseFromHttpUrl(url: URL): String? {
val urlConnection = url.openConnection() as HttpURLConnection
try {
val `in` = urlConnection.getInputStream()
val scanner = Scanner(`in`)
scanner.useDelimiter("\\A")
val hasInput = scanner.hasNext()
return if (hasInput) {
scanner.next()
} else {
null
}
} catch (ex: Exception) {
Log.d(TAG, ex.toString())
} finally {
urlConnection.disconnect()
}
return null
}
}
The Activity:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_network)
}
override fun onResume() {
super.onResume()
val scope = CoroutineScope(Job() + Dispatchers.IO)
var nwMutipleItemsJob = scope.async(Dispatchers.IO)
{
var nwURL = NetworkUtils.buildURLAll()
val response = NetworkUtils.getResponseFromHttpUrl(nwURL)
response
}
scope.async(Dispatchers.Default)
{
var response = nwMutipleItemsJob.await()
var jsonResponse = JSONArray(response)
var msg = "$response\n\n"
for(i in 0 until jsonResponse.length())
{
var jsonItem = jsonResponse.getJSONObject(i)
// var userid = jsonItem.getInt("userId")
// var id = jsonItem.getInt("adult")
// var title = jsonItem.getString("title")
// var body = jsonItem.getString("body")
// msg += "item $i\n\nid = \n = $id\n"
}
withContext(Dispatchers.Main)
{
tvJSONMultipleItemDisplay.text = msg
}
}
}
}
layout activity:
<ScrollView
android:layout_width="wrap_content"
android:layout_height="match_parent">
<TextView
android:id="#+id/tvJSONMultipleItemDisplay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
/>
</ScrollView>
However it does not work and does not display anything. ? Did you find any error ?.
Please add logs in your getResponseFromHttpUrl and onResume that will help you to find and fix the issue.
How to debug ?.
Ref : https://stackoverflow.com/a/62019186/9909365
On the Android, the log of device display on Tab Logcat, not on console as the Chrome. You can see the log in this tab, and remember build your App in the debug mode.
Edit: If you want to see all the log, you can switch the option Show only Application selected to No filter
For more information, you can find in this link
How to add logs ?
Ref : https://developer.android.com/studio/debug/am-logcat
The Logcat window in Android Studio displays system messages, such as when a garbage collection occurs, and messages that you added to your app with the Log class. It displays messages in real time and keeps a history so you can view older messages.
To display just the information of interest, you can create filters, modify how much information is displayed in messages, set priority levels, display messages produced by app code only, and search the log. By default, logcat shows the log output related to the most recently run app only.
When an app throws an exception, logcat shows a message followed by the associated stack trace containing links to the line of code.
As of Android Studio 2.2, the Run window also displays log messages for the current running app. Note that you can configure the logcat output display, but not the Run window.
Write log messages
Ref : https://developer.android.com/studio/debug/am-logcat#WriteLogs
The Log class allows you to create log messages that appear in logcat. Generally, you should use the following log methods, listed in order from the highest to lowest priority (or, least to most verbose):
Log.e(String, String) (error)
Log.w(String, String) (warning)
Log.i(String, String) (information)
Log.d(String, String) (debug)
Log.v(String, String) (verbose)
I am using android javamail library 1.6.2. I am trying to read mails and return it as a list of custom objects in fragment to display them in recycler view. The code I am using for reading mails is:
fun readMails(host: String, port: String,
username: String, password: String): List<Mail>? {
var folder: Folder? = null
var store: Store? = null
return try {
val properties = Properties()
properties[HOST] = host
properties[PORT] = port
properties[START_TLS] = "true"
val session = Session.getDefaultInstance(properties)
// Create IMAP store object and connect with the server
store = session.getStore(PROTOCOL)
store.connect(host, username, password)
// Create folder object and open it in read-only mode
folder = store.getFolder(FOLDER_TYPE)
folder.open(Folder.READ_ONLY)
// Fetch messages from the folder and print in a loop
val messages = folder.messages
val mails = messages.map {
Mail(
messageNumber = it.messageNumber,
subject = it.subject,
senders = it.from.toList().map { address ->
MailAddress(
type = address.type,
)
},
content = parseContent(it.content as Multipart)
)
}
Log.d(TAG, "readMails: $mails")
mails
} catch (e: NoSuchProviderException) {
Log.e(TAG, "NoSuchProviderException: ${e.localizedMessage}")
null
} catch (e: MessagingException) {
Log.e(TAG, "MessagingException: ${e.localizedMessage}")
null
} catch (e: Exception) {
Log.e(TAG, "Exception: ${e.localizedMessage}")
null
} finally {
folder?.close(false)
store?.close()
}
}
In fragment I am trying to read mails using:
viewLifecycleOwner.lifecycleScope.launch {
val emails = MailHelper.readMails(
host = "",
port = "",
username = "",
password = ""
)
mailAdapter.submitList(emails)
}
The problem is that I can print mails in console but I can only print them using GlobalScope.launch {}. If I use that I cannot display then in recyclerview using submitList() to the adapter. If I use viewLifecycleOwner.lifecycleScope.launch {} I keep getting android.os.NetworkOnMainThreadException.
Your problem arises from the fact that viewLifecycleOwner.lifecycleScope is bound to Dispatchers.Main.immediate which is confined to the application 'Main' or 'UI' thread meaning your coroutine starts executing on UI thread and you get the error.
To solve this you should pass IO dispatcher to the launch function
viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) {
val emails = MailHelper.readMails(
host = "",
port = "",
username = "",
password = ""
)
mailAdapter.submitList(emails)
}
This will make sure that your coroutine executes on thread pool allocated for IO and not on the main thread.
Note : Dispatchers.IO can't be used to update UI, only UI thread can do that
The language used is Kotlin, implemented by Android Studio.
I want to change the EditText existing in the xml of the layout folder into String type and send it as Kafka value, but I keep getting an error somewhere.
It is said that it is impossible to conclude the visible error theory. Where exactly is the problem?
class Registration() : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.Sign_Up)
val rc: Button = findViewById(R.id.Registration_Completed)
val id: EditText = findViewById(R.id.ID)
val pw: EditText = findViewById(R.id.PW)
val UserID = id.text.toString() //convert id to string
val UserPW = pw.text.toString() //convert pw to string
rc.setOnClickListener {
val intent = Intent(this, next_activity::class.java)
Producer()
Toast.makeText(this, "registration completed", Toast.LENGTH_SHORT).show()
startActivity(intent)
}
}
Below is the Producer code
class Producer {
companion object {
#JvmStatic
fun main(args: String){
val TOPIC= "test"
val SERVERS = "localhost:9092"
val configs = Properties()
configs.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, SERVERS)
configs.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,
"org.apache.kafka.common.serialization.StringSerializer")
configs.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,
"org.apache.kafka.common.serialization.StringSerializer")
val producer = KafkaProducer<String, String>(configs)
var record: ProducerRecord<String, String> =ProducerRecord(TOPIC,"print")
Up to this point, the output is normal.
producer.send(ProducerRecord(TOPIC, UserID))
producer.send(ProducerRecord(TOPIC, UserPW))
producer.close()
try {
producer.send(ProducerRecord<String, String> (TOPIC, "SUCCESS!"))
} catch (exception:Exception)
{
exception.printStackTrace()
}
finally { producer.close() }
The connection may not work well because the cord is partially cut.
I used the id and pw variables in the Producer by dragging the EditText to Internal fun() under the Registration class.
Producer and connection, how to pull variables, etc., function errors, etc. Which is the problem?
NOTE: I was able to figure this out. There is no need to change the rules in Firebase. See code below.
ORIGINAL POST
I have an IOS app and I decided to build the Android/Kotlin version and I'm having a hard time with Firebase/isEmailVerify. I'm able to register a new user and send the email for verification, but, if I don't verify, I'm still able to login. I'm new at Kotlin. Any help is greatly appreciated.
UPDATED CODE
class LoginActivity : AppCompatActivity() {
lateinit var auth: FirebaseAuth
private var emailVerifier: Boolean = true
private val emailVerificationAlert = { _: DialogInterface, _: Int ->
Toast.makeText(this.applicationContext, android.R.string.yes, Toast.LENGTH_SHORT).show()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
auth = FirebaseAuth.getInstance()
}
private fun verifyEmail() {
val user = FirebaseAuth.getInstance().currentUser
if (user != null) {
emailVerifier = user.isEmailVerified()
}
if (emailVerifier) {
finish()
} else {
userDidNotVerify()
auth.signOut()
}
}
fun loginBtnClicked(view: View) {
val email = loginEmailTxt.text.toString()
val password = loginPasswordTxt.text.toString()
auth.signInWithEmailAndPassword(email, password)
.addOnSuccessListener { exception ->
println("USER LOGGED IN")
verifyEmail()
}
.addOnFailureListener { exception ->
Log.e("Exception", "Could not sign in user - ${exception.localizedMessage}")
}
}
private fun userDidNotVerify() {
val builder = android.app.AlertDialog.Builder(this)
with(builder) {
this.setTitle("Confirm your email address.")
this.setMessage("A confirmation email has been sent to" + " " + (loginEmailTxt.text) + " " +
"." + " " + "Click on the confirmation link to activate your account")
this.setPositiveButton("OK", DialogInterface.OnClickListener(function = emailVerificationAlert))
this.show()
}
}
fun loginCreateClicked(view: View) {
val createIntent = Intent(this, CreateUserActivity::class.java)
startActivity(createIntent)
}
}
It's expected that the user can still sign in before the email is verified. This provides a way for your app to allow the user to request another verification email to be sent, in case something happened to the first one.
If you want to restrict what the user can do before the email is verified, you can check isEmailVerfied() on the UserInfo object, and you can use the auth.token.email_verified in security rules to limit their access to databases and storage also provided by Firebase.