I'm very new to Kotlin so please bear with me. I want to open a SQLite database or create it if it doesn't exist yet. Afterwards I'd run the appropriate statements to make a table, etc. I'm trying to use SQLiteDatabase. The line of code I'm trying is:
val db = SQLiteDatabase.openOrCreateDatabase("database.db",null, SQLiteDatabase.OPEN_READWRITE)
I get this runtime error when I try the app:
android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 1294 SQLITE_CANTOPEN_ENOENT[1294]): Could not open database
I'm not picky about the database, I just want an easy way to read and write to one from within my function.
This is the surrounding code:
package com.google.firebase.codelab.barcode_scanning
// Date/time formatting functions
import android.database.sqlite.SQLiteDatabase
import android.graphics.Color
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.item_row.view.*
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
class QrCodeAdapter(private val qrList: ArrayList<QrCode>) : RecyclerView.Adapter<QrCodeAdapter.QrHolder>() {
//
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QrHolder {
return QrHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_row, parent, false))
}
override fun getItemCount() = qrList.size
override fun onBindViewHolder(holder: QrHolder, position: Int) {
//internal var dbHelper = DatabaseHelper(this)
with(qrList[position]) {
var objname = "Barcode Not Found"
var statustext = ""
// status: 0 = no record, 1 = dirty, 2 = clean, 3 = dwell, 4: dwell done
var status = 0
var lastcleaned = ""
// objcategory: 0 = no record, 1 = contact object, 2 = dwell item
var objcategory = 0
var objcategorytext = ""
// initial setup of current date/time
var unixtime = System.currentTimeMillis()
var currenttime = LocalDateTime.now()
var timeformat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")
var testtime = currenttime.format(timeformat).toString()
//val db = SQLiteDatabase.openDatabase("//app/maindb.db", null, 0);
val db = SQLiteDatabase.openOrCreateDatabase("database.db",null, null)
//val sql = "SELECT COUNT(*) FROM main"
//val statement = db.compileStatement(sql)
//val result = statement.simpleQueryForLong()
//Convert barcode output to string
var barcodevalue = this.value.toString()
// hide settings
holder.itemView.textSettingsTitle.visibility=View.GONE
holder.itemView.textboxName.visibility=View.GONE
}
Related
I have a problem with this test code:
package mainPackage.tests
import com.google.firebase.firestore.FirebaseFirestore
import mainPackage.model.RepositoryMockup
import org.junit.Assert.*
import org.junit.Before
import org.junit.Test
class RepositoryTest {
#Test
fun testWriteNewUser() {
val repository = RepositoryMockup()
val email = "test.first#pwr.edu.pl"
val pass = "testpassword123"
val isATeacher = true
val task = repository.writeNewUser(pass, email, isATeacher)
task.addOnCompleteListener {
assertTrue(it.isSuccessful)
}
}
}
Here is an error:
And here is a class that I am testing:
package mainPackage.model
import com.google.firebase.firestore.FirebaseFirestore
import android.util.Log
import com.google.android.gms.tasks.Task
import com.google.firebase.firestore.FirebaseFirestoreException
import mainPackage.utils.Checks
const val TAG = "FIRESTORE"
class RepositoryMockup {
//--------------------------------
//Firebase functions
fun writeNewUser(pass: String, email: String, isATeacher: Boolean?) : Task<Void> {
val database = FirebaseFirestore.getInstance()
val myRef = database.collection("Users").document(email)
val newUser = hashMapOf(
"is_a_teacher" to isATeacher,
"pass" to pass
)
myRef.set(newUser)
.addOnSuccessListener { Log.d(TAG, "User successfully added") }
.addOnFailureListener { e -> Log.w(TAG, "Error writing user", e) }
return myRef.set(newUser)
}
}
It's only a small part of it. I hve tried a lot of things but they didn't help me.
I always got an error.
This class works perfect so the firebase was added correct.
Help me to fix this error.
I'm trying to translate my app from Java to Kotlin.
I'm managing database with AnKo SQLite
All is OK except listviews with CursorLoaders : I can't find how to replace CursorLoader while using AnKo SQLite.
(and same problem with expandableListViews)
Can somebody help me please?
OK, here is my solution... I don't know if it is the best :
create a new kotlin class "MyCursorLoader" that extends CursorLoader
set the primary constructor like this :
class MyCursorLoader(
mContext: Context,
val mTableName: String,
var mProjection: Array<String>? = null,
var mSelection: String = "1",
var mSelectionArgs: Array<String> = emptyArray(),
var mGroupBy: String = MySqlHelper.ID,
var mHaving: String = "",
var mSortOrder: String = "${MySqlHelper.ID} ASC",
var mLimit: String = "",
var mDistinct: Boolean = true
): CursorLoader(mContext) {
val mObserver: Loader<Cursor>.ForceLoadContentObserver = Loader<Cursor>(mContext).ForceLoadContentObserver()
var mCancellationSignal: CancellationSignal? = null
override the OnLoadInBackground method with te same code than built-in one, just replacing the val cursor = ContentResolverCompat.query(... line with :
val cursor = MySqlHelper.instance.readableDatabase.query(
mDistinct, mTableName, mProjection, mSelection, mSelectionArgs, mGroupBy, mHaving, mSortOrder, mLimit, mCancellationSignal)
So no need to recreate a dataprovider in manifest, no need to deal with Uri's... I can use MyCursorLoader exactly like built-in CursorLoader, calling it like this :
override fun onCreateLoader(id: Int, args: Bundle?): Loader<Cursor> {
when (id) {
DAY_HEADER_LOADER ->
return MyCursorLoader(mContext, TABLE_EVENTS, arrayOf(ID, DAY), mGroupBy = DAY, mSortOrder = "$DAY DESC")
...
}
}
Let me know if ther is a better solution.
Hope that can help.
I need to have two different schema in one app using realm db.
It seems that should work below solution:
open class AModel : RealmObject() {
var a: Int = 0
}
open class BModel : RealmObject() {
var b: Int = 0
}
open class XModel : RealmObject() {
var x: Int = 0
}
open class YModel : RealmObject() {
var y: Int = 0
}
#RealmModule(classes = [AModel::class,BModel::class])
open class Schema1
val conf1 = new RealmConfiguration.Builder()
.name("db1.realm")
.schemaVersion(1)
.modules(Schema1())
.build();
#RealmModule(classes = [XModel::class,YModel::class])
open class Schema2
val conf2 = new RealmConfiguration.Builder()
.name("db2.realm")
.schemaVersion(2)
.modules(Schema2())
.build();
but when app starts and calls Realm.setDefaultConfiguration(conf1), it prints below error:
com.example.XModel is not part of the schema for this Realm
So it seems that I miss something in configuration but looking at docs I cannot figure out what. So what I miss?
The problem is that you set the schema version of conf2 as a second version, but the first one was never created. Change it for this:
...
val conf2 = new RealmConfiguration.Builder()
.name("db2.realm")
.schemaVersion(1)
.modules(Schema2())
.build();
I'm trying to expose an API for a CorDapp and the functions are not displaying. When looking at an example (https://github.com/roger3cev/obligation-cordapp), I receive the following page: https://imgur.com/a/ifOdrAd, however when I load my CorDapp, it says there are no installed Cordapps and /api on the localhost returns a 404. In the project, I feel the problem lies somewhere here: https://github.com/PronoyC/InsureFlight/tree/master/cordapp/src/main/kotlin/com/insureflight. I know this is very vague but I cannot find any errors that indicate a specific area. Any help would be appreciated.
InsureFlightApi.kt:
package com.insureflight
import net.corda.core.contracts.Amount
import net.corda.core.contracts.UniqueIdentifier
import net.corda.core.messaging.CordaRPCOps
import net.corda.core.utilities.OpaqueBytes
import net.corda.core.utilities.getOrThrow
import com.insureflight.flows.IssuePolicy
import com.insureflight.flows.PayoutPolicy
import net.corda.finance.contracts.asset.Cash
import net.corda.finance.contracts.getCashBalances
import net.corda.finance.flows.CashIssueFlow
import java.util.*
import javax.ws.rs.GET
import javax.ws.rs.Path
import javax.ws.rs.Produces
import javax.ws.rs.QueryParam
import javax.ws.rs.core.MediaType
import javax.ws.rs.core.Response
import javax.ws.rs.core.Response.Status.BAD_REQUEST
import javax.ws.rs.core.Response.Status.CREATED
#Path("insureflight")
class InsureFlightApi(val rpcOps: CordaRPCOps) {
private val myIdentity = rpcOps.nodeInfo().legalIdentities.first()
#GET
#Path("me")
#Produces(MediaType.APPLICATION_JSON)
fun me() = mapOf("me" to myIdentity)
#GET
#Path("peers")
#Produces(MediaType.APPLICATION_JSON)
fun peers() = mapOf("peers" to rpcOps.networkMapSnapshot()
.filter { nodeInfo -> nodeInfo.legalIdentities.first() != myIdentity }
.map { it.legalIdentities.first().name.organisation })
#GET
#Path("policies")
#Produces(MediaType.APPLICATION_JSON)
fun policies() = rpcOps.vaultQuery(Policy::class.java).states
#GET
#Path("cash")
#Produces(MediaType.APPLICATION_JSON)
fun cash() = rpcOps.vaultQuery(Cash.State::class.java).states
#GET
#Path("cash-balances")
#Produces(MediaType.APPLICATION_JSON)
fun getCashBalances() = rpcOps.getCashBalances()
#GET
#Path("self-issue-cash")
fun selfIssueCash(#QueryParam(value = "amount") amount: Int,
#QueryParam(value = "currency") currency: String): Response {
// 1. Prepare issue request.
val issueAmount = Amount(amount.toLong(), Currency.getInstance(currency))
val notary = rpcOps.notaryIdentities().firstOrNull() ?: throw IllegalStateException("Could not find a notary.")
val issueRef = OpaqueBytes.of(0)
val issueRequest = CashIssueFlow.IssueRequest(issueAmount, issueRef, notary)
// 2. Start flow and wait for response.
val (status, message) = try {
val flowHandle = rpcOps.startFlowDynamic(CashIssueFlow::class.java, issueRequest)
val result = flowHandle.use { it.returnValue.getOrThrow() }
CREATED to result.stx.tx.outputs.single().data
} catch (e: Exception) {
BAD_REQUEST to e.message
}
// 3. Return the response.
return Response.status(status).entity(message).build()
}
#GET
#Path("issue-policy")
fun issuePolicy(#QueryParam(value = "premium") premium: Int,
#QueryParam(value = "currency") currency: String,
#QueryParam(value = "client") client: String,
#QueryParam(value = "underwriter") underwriter: String,
#QueryParam(value = "flight") flight: String,
#QueryParam(value = "fStatus") fStatus: String): Response {
// 1. Create a premium object.
val issuePremium = Amount(premium.toLong() * 100, Currency.getInstance(currency))
// 2. Start the IssuePolicy flow. We block and wait for the flow to return.
val (status, message) = try {
val flowHandle = rpcOps.startFlowDynamic(
IssuePolicy.Initiator::class.java,
issuePremium,
client,
underwriter,
flight,
fStatus,
true
)
val result = flowHandle.use { it.returnValue.getOrThrow() }
CREATED to "Transaction id ${result.id} committed to ledger.\n${result.tx.outputs.single().data}"
} catch (e: Exception) {
BAD_REQUEST to e.message
}
// 3. Return the result.
return Response.status(status).entity(message).build()
}
#GET
#Path("payout-policy")
fun settlePolicy(#QueryParam(value = "id") id: String,
#QueryParam(value = "delayedMinutes") delayedMinutes: Int,
#QueryParam(value = "fStatus") fStatus: String): Response {
// 1. Get party objects for the counterparty.
val linearId = UniqueIdentifier.fromString(id)
// 2. Start the SettlePolicy flow. We block and wait for the flow to return.
val (status, message) = try {
val flowHandle = rpcOps.startFlowDynamic(
PayoutPolicy.Initiator::class.java,
linearId,
delayedMinutes,
fStatus,
true
)
flowHandle.use { flowHandle.returnValue.getOrThrow() }
CREATED to "Policy $linearId has been settled."
} catch (e: Exception) {
BAD_REQUEST to e.message
}
// 3. Return the result.
return Response.status(status).entity(message).build()
}
}
InsureFlightPlugin.kt (ObligationPlugin.kt is very similar to this):
package com.insureflight
import net.corda.core.messaging.CordaRPCOps
import net.corda.webserver.services.WebServerPluginRegistry
import java.util.function.Function
class InsureFlightPlugin : WebServerPluginRegistry {
override val webApis: List<Function<CordaRPCOps, out Any>> = listOf(Function(::InsureFlightApi))
override val staticServeDirs: Map<String, String> = mapOf(
"policy" to javaClass.classLoader.getResource("policyWeb").toExternalForm()
)
}
Kid101 is correct. You've to register the InsureFlightPlugin, like done here: obligation-cordapp/kotlin-source/src/main/resources/META-INF/services/net.corda.webserver.services.WebServerPluginRegistry
I'm working with DynamoDB at the moment. I want to use a conditional write to update a record if that record has a date that is older than the new record date field.
Is there a way to compare DateTime types for conditional writes? Or is it currently only for integers, strings and streams?
Thanks.
Since you mentioned you are using ISO-8601 with the String datatype, it is easy to use the comparing operators (<, <=, etc.) in your conditional expression because of the lexicographical ordering described in this answer.
Here is a quick example where I used Java 8's time and ran it against DynamoDB Local:
import com.google.common.collect.ImmutableMap;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.spec.UpdateItemSpec;
import com.amazonaws.services.dynamodbv2.model.AttributeDefinition;
import com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException;
import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
import com.amazonaws.services.dynamodbv2.model.KeySchemaElement;
import com.amazonaws.services.dynamodbv2.model.KeyType;
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;
import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType;
import com.amazonaws.services.dynamodbv2.util.Tables;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
public class DynamoDBStackoverflow {
public static final String TABLE_NAME = "exampleTable";
private static final String HASH_KEY = "hashAttributeName";
public static void main(String[] args) {
AWSCredentials awsCredentials = new BasicAWSCredentials("key", "secret");
AmazonDynamoDB client = new AmazonDynamoDBClient(awsCredentials);
client.setEndpoint("http://localhost:4000");
DynamoDB dynamoDB = new DynamoDB(client);
if (Tables.doesTableExist(client, TABLE_NAME)) {
client.deleteTable(TABLE_NAME);
}
final CreateTableRequest createTableRequest = new CreateTableRequest()
.withTableName(TABLE_NAME)
.withKeySchema(new KeySchemaElement(HASH_KEY, KeyType.HASH))
.withAttributeDefinitions(new AttributeDefinition(HASH_KEY, ScalarAttributeType.S))
.withProvisionedThroughput(new ProvisionedThroughput(15L, 15L));
final Table table = dynamoDB.createTable(createTableRequest);
final Instant now = Instant.now();
final Instant before = now.minus(10, ChronoUnit.MINUTES).truncatedTo(ChronoUnit.MINUTES);
final Instant after = now.plus(10, ChronoUnit.MINUTES);
System.out.println("Before: " + before.toString());
System.out.println("Now: " + now.toString());
System.out.println("After: " + after.toString());
table.putItem(new Item().withPrimaryKey(HASH_KEY, "1")
.withString("dateField", before.toString()));
table.putItem(new Item().withPrimaryKey(HASH_KEY, "2")
.withString("dateField", now.toString()));
System.out.println("put items");
table.scan().forEach(System.out::println);
UpdateItemSpec updateItemSpec = new UpdateItemSpec().withPrimaryKey(HASH_KEY, "1")
.withConditionExpression("dateField < :beforeDate")
.withValueMap(ImmutableMap.of(":beforeDate", before.toString()))
.withUpdateExpression("SET dateField = :beforeDate");
try {
table.updateItem(updateItemSpec);
throw new RuntimeException();
} catch (ConditionalCheckFailedException ccfe) {
System.out.println("expected conditional write with < to fail when they are equal");
}
updateItemSpec = new UpdateItemSpec().withPrimaryKey(HASH_KEY, "2")
.withConditionExpression("dateField < :beforeDate")
.withValueMap(ImmutableMap.of(":beforeDate", before.toString()))
.withUpdateExpression("SET dateField = :beforeDate");
try {
table.updateItem(updateItemSpec);
throw new RuntimeException();
} catch (ConditionalCheckFailedException ccfe) {
System.out.println("expected conditional write with < to fail when new is before");
}
updateItemSpec = new UpdateItemSpec().withPrimaryKey(HASH_KEY, "1")
.withConditionExpression("dateField <= :beforeDate")
.withValueMap(ImmutableMap.of(":beforeDate", before.toString()))
.withUpdateExpression("SET dateField = :beforeDate");
try {
table.updateItem(updateItemSpec);
} catch (ConditionalCheckFailedException ccfe) {
System.out.println("should not happen");
throw new RuntimeException();
}
updateItemSpec = new UpdateItemSpec().withPrimaryKey(HASH_KEY, "2")
.withConditionExpression("dateField <= :afterDate")
.withValueMap(ImmutableMap.of(":afterDate", after.toString()))
.withUpdateExpression("SET dateField = :afterDate");
try {
table.updateItem(updateItemSpec);
} catch (ConditionalCheckFailedException ccfe) {
System.out.println("should not happen");
throw new RuntimeException();
}
System.out.println();
System.out.println("after all updates");
table.scan().forEach(System.out::println);
}
}
And the output:
Before: 2015-06-08T15:57:00Z
Now: 2015-06-08T16:07:08.893Z
After: 2015-06-08T16:17:08.893Z
put items
{ Item: {hashAttributeName=1, dateField=2015-06-08T15:57:00Z} }
{ Item: {hashAttributeName=2, dateField=2015-06-08T16:07:08.893Z} }
expected conditional write with < to fail when they are equal
expected conditional write with < to fail when new is before
after all updates
{ Item: {hashAttributeName=1, dateField=2015-06-08T15:57:00Z} }
{ Item: {hashAttributeName=2, dateField=2015-06-08T16:17:08.893Z} }
DynamoDB doesn't understand dates. If you save the date as long, ms/s since epoch, then you can use arithmetic <, >=, etc.
If you use a String presentation, then it all depends if you can find the right DynamoDB operator to query on two of them.
I personally use the former, thus doing it with calculus.