Bluetooth LE - How do i get Advertisement Interval in milliseconds? - java

I have to get the Advertisement Interval in milliseconds. I used result.periodicAdvertisingInterval but this returns 0. I have to implement something like this:
private val scanCallback = object : ScanCallback(){
#RequiresApi(Build.VERSION_CODES.N)
#SuppressLint("MissingPermission", "NotifyDataSetChanged")
override fun onScanResult(callbackType: Int, result: ScanResult) {
val scanJob = CoroutineScope(Dispatchers.Main).launch {
val tag = deviceMap.computeIfAbsent(result.device.address) {
val newTag = BleTag(result.device.name ?: "Unbekannt", result.device.address, result.rssi , result.scanRecord?.bytes, "")
deviceList.add(newTag)
newTag
}
tag.name = result.device.name ?: "Unbekannt"
tag.rssi = result.rssi
tag.advertisementData = result.scanRecord?.bytes
}
deviceList.sortBy {result.rssi }
recyclerView.adapter?.notifyDataSetChanged()
menu.findItem(R.id.count).title = "Geräte: " + deviceList.size
super.onScanResult(callbackType, result)
}
override fun onScanFailed(errorCode: Int) {
super.onScanFailed(errorCode)
Log.e("Scan failed","")
}
}

This result is obtained by subtracting the timestamps of two consecutive advertisements of the same device.

Related

Screen is not responding as I set a result to another edit text when using RxJava

I'm implement an TextInputEditText with RxBinding.
Problem: When I do some math operation on first TextInputEditText and set the result to another TextInputEditText, The screen is not responding. When I start to type another digit, its not displayed in the edit text. I know why this happened, but don't know how to fix. For more detail, please check the code below.
Code:
class NumberSystemFragment : Fragment() {
override fun onCreateView() { ... }
override fun onViewCreated() {
binding?.run {
// It still ok if just observe a single edit text
etBinary.observeInput().subscribe {
val dec = it.fold(0L) { acc, el ->
(acc * 2) + el.digitToInt(radix = 2)
}
val oct = dec.toString(8)
val hex = dec.toString(16)
etDecimal.setText(dec.toString())
etOctal.setText(oct)
etHexadecimal.setText(hex)
}
// But, when I add more EditText, the screen will not responding.
// I know why this can happen, because when I set the result from operation above,
// and display it to another EditTexts, then the other EditText will begin to observe its input too.
// Then the racing condition or whatever it is, will occur.
etDecimal.observeInput().subscribe {
val bin = it.toLong().toString(2)
val oct = it.toLong().toString(8)
val hex = it.toLong().toString(16)
etBinary.setText(bin)
etOctal.setText(oct)
etHexadecimal.setText(hex)
}
}
}
private fun <T : EditText> T.observeInput() =
RxTextView.textChanges(this)
.skipInitialValue()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.map(CharSequence::toString)
.publish()
.refCount()
}
Sorry, I'm new with RxJava, RxBinding, etc.
Two issues.
You have created a feedback loop by setting text on the other editors, which then trigger updates on the current editor.
If your code crashes, it will stop listening to values.
First of all, make these extension method changes:
private fun <T: EditText> T.observeInput() =
RxTextView.textChanges(this)
.skipInitialValue()
.map(CharSequence::toString) // <------------------ order matters
.distinctUntilChanged() // <----------------------- order matters
.observeOn(AndroidSchedulers.mainThread())
.publish()
.refCount()
private fun TextInputEditText.setText(text: CharSequence, onlyIfChanged: Boolean) {
if (onlyIfChanged) {
if (Objects.equals(this.text.toString(), text.toString())) {
return;
}
}
this.setText(text);
}
Then, update your onNext handlers:
// etBinary
// store calculation data
try {
Log.d("XYZ-etBinary", t);
val decResult = t.fold(0L) { acc, element ->
(acc * 2) + element.digitToInt(2)
}
val octResult = decResult.toString(8)
val hexResult = decResult.toString(16).uppercase()
// and display the results to another edit text which corresponds with their radix representation
etDecimal.setText(decResult.toString(), true)
etOctal.setText(octResult, true)
etHexadecimal.setText(hexResult, true)
} catch (e: Throwable) {
Log.e("XYZ-etBinary", e.message.toString())
}
// etDecimal
// store calculation data
try {
Log.d("XYZ-etDecimal", t);
val binResult = t.toLong().toString(2)
val octResult = t.toLong().toString(8)
val hexResult = t.toLong().toString(16).uppercase()
// and display the results to another edit text which corresponds with their radix representation
etBinary.setText(binResult, true)
etOctal.setText(octResult, true)
etHexadecimal.setText(hexResult, true)
} catch (e: Throwable) {
Log.e("XYZ-etDecimal", e.message.toString())
}
Also posted it as a Pull Request on your repo: https://github.com/dansampl/EditTextWithRxJavaSampleApp/pull/1/files

How to highlight days from API in highlighable calendar in Kotlin?

I have API that post and get dates:
this is the data class:
data class PlannerGet(
val date: String,
val endTime: String,
val id: Int,
val location: String,
val note: String,
val startTime: String,
val title: String
)
and i am using this library for the calendar:
https://github.com/VarunBarad/Highlightable-Calendar-View
now in the fragment i was able to highlight certain days like this:
HighlightableCalendarView.dayDecorators = listOf(
DayDecorator(
Calendar.getInstance().apply {
set(Calendar.DAY_OF_MONTH, 4)
},
Color.parseColor("#ffffff"),
Color.parseColor("#ff0000")
),
)
but i want to highlight the days from API
i tried to make it like this:
HighlightableCalendarView.dayDecorators = listOf(
DayDecorator(
Calendar.getInstance().apply {
set(PlannerGet.date)
},
Color.parseColor("#ffffff"),
Color.parseColor("#ff0000")
),
)
but i am having a problem with "set" it show "None of the following functions can be called with the arguments supplied."
i tried to add "toInt()" and still the same problem.
what is the correct way to achieve this?
This is because the params which you are passing do not match the required params.
Calendar.getInstance().apply {
set(Calendar.DAY_OF_MONTH, 4)
}
The set functions accept the int field, int value but you are passing the params as the string
PlannerGet.date
The function set
public void set(int field, int value) {
throw new RuntimeException("Stub!");
}
If you want the date to be passed from the API dates please convert the string dates to java Date object.
SOLUTION:
if (response?.body().toString() == "[]") {
}
else if (response.isSuccessful) {
response.body()?.forEach {
getplanner.add(it)
Log.e("gggg gggg",getplanner.toString())
Log.e("gggg ddddd",getplanner[0].date)
}
val list = arrayListOf<DayDecorator>()
for (dsds in getplanner) {
list.add( DayDecorator(
Calendar.getInstance().apply {
// getplanner[0].date
val input_date = dsds.date
val format1 = SimpleDateFormat("yyyy-MM-dd")
var dt1: Date? = null
dt1 = format1.parse(input_date)
val format2: DateFormat = SimpleDateFormat("dd")
val strMonth: String = format2.format(dt1)
val month = strMonth.toInt()
Log.e("dateinplanner", "" + month)
set(Calendar.DAY_OF_MONTH, month)
},
Color.parseColor("#ffffff"),
Color.parseColor("#1AB7B8")
))
}
HighlightableCalendarView.dayDecorators = list

Identifying a SIM card slot with PHONE_ACCOUNT_ID in Android CallLogCalls

In dual-SIM card mobiles I manage to differentiate SIM cards in the calllog using the PHONE_ACCOUNT_ID property as shown in the code below. Now I need to know what SIM card actually was use (1 or 2) to make or receive the call. PHONE_ACCOUNT_ID shows something like this 8953011201104578086F for and one SIM card and similar, but no equal to the other. This was tested in a Samsung mobile:
fun readCallLog() {
val cursor = context.contentResolver.query(CallLog.Calls.CONTENT_URI,null, null, null, CallLog.Calls.DATE + " DESC")
val number = cursor?.getColumnIndex(CallLog.Calls.NUMBER)
val date = cursor?.getColumnIndex(CallLog.Calls.DATE)
val type = cursor?.getColumnIndex(CallLog.Calls.TYPE)
val account_id = cursor?.getColumnIndex(CallLog.Calls.PHONE_ACCOUNT_ID)
val tmp : MutableList<List<String?>> = mutableListOf()
while (cursor?.moveToNext() == true ) {
val call_number = if (number != null) cursor.getString(number) else ""
val call_date = if(date != null) cursor.getString(date) else ""
val call_type = if(type != null) cursor.getInt(type).toString() else ""
val call_account_id = if(account_id != null) cursor.getString(account_id) else ""
tmp.add( listOf(call_number, call_date, call_type, call_account_id))
}
}
You can get information on SIM cards with SubscriptionManager.getActiveSubscriptionInfoList().
On some devices, Call.PHONE_ACCOUNT_ID equals subscriptionInfo.getSubscriptionId(), however on other devices (your case) subscriptionInfo.getIccId() is a substring of it, so you need to check both.
See also SubscriptionManager reference.
The official way is to check the account-id (documentation here), but on some devices it just returns the SIM card slot index, so here's the code with a workaround (from Android 6.0 (Marshmallow)):
fun getSimSlotIndexFromAccountId(context: Context, accountIdToFind: String): Int {
// This is actually the official data that should be found, as on the emulator, but sadly not all phones return here a proper value
val telecomManager = context.getSystemService<TelecomManager>()
telecomManager.callCapablePhoneAccounts.forEachIndexed { index, account: PhoneAccountHandle ->
val phoneAccount: PhoneAccount = telecomManager.getPhoneAccount(account)
val accountId: String = phoneAccount.accountHandle
.id
if (accountIdToFind == accountId) {
return index
}
}
accountIdToFind.toIntOrNull()?.let {
if (it >= 0)
return it
}
return -1
}
Usage:
val simIdColumnIndex = callLogCursor.getColumnIndex(CallLog.Calls.PHONE_ACCOUNT_ID)
val accountId: String = callLogCursor.getString(simIdColumnIndex)
val simCardSlotIndex = getSimSlotIndexFromAccountId(applicationContext, accountId)
I've reported about this issue (that some devices don't follow official API) here:
Bug: on some devices, PHONE_ACCOUNT_ID just returns the SIM-card slot index

Junit expected value exception

I am writing a test to test my repository. I noticed that the return expected value matches the actual value except that the actual value is wrapped within "<>".
I do not know why this is happening.
#ExperimentalCoroutinesApi
#RunWith(AndroidJUnit4::class)
#Config(sdk = [Build.VERSION_CODES.O_MR1])
class MovieRepositoryTest{
#get:Rule
var instantExecutorRule = InstantTaskExecutorRule()
private val movie1 = MovieEntity("Title1", "https://movie1.jpg", 3, "Movie1Overview", "Jan 2021")
private val movie2 = MovieEntity("Title2", "https://movie2.jpg", 3, "Movie2Overview", "Jan 2022")
private val movie3 = MovieEntity("Title3", "https://movie3.jpg", 3, "Movie2Overview", "Jan 2023")
private val remoteTasks = mutableListOf(movie3).sortedBy { it.id }
private val localTasks = mutableListOf(movie1, movie2).sortedBy { it.id }
private lateinit var tasksRemoteDataSource: FakeDataSource<MovieEntity>
private lateinit var tasksLocalDataSource: FakeDataSource<MovieEntity>
private lateinit var moviesRepository: MoviesRepoInterface
#Before
fun createRepository() {
tasksRemoteDataSource = FakeDataSource(remoteTasks.toMutableList())
tasksLocalDataSource = FakeDataSource(localTasks.toMutableList())
moviesRepository = MovieRepository(tasksRemoteDataSource, tasksLocalDataSource)
}
#Test
fun getRemoteMovies_RequestAllMovie()= runBlockingTest{
val movies = moviesRepository.getMovies(false, ApplicationProvider.getApplicationContext())
assertEquals(movies.getOrAwaitValue(), IsEqual<List<MovieEntity>>(localTasks))
}
}
Error
java.lang.AssertionError:
Expected :[com.darotapp.cornflix.data.local.database.MovieEntity#3843fe46, com.darotapp.cornflix.data.local.database.MovieEntity#1b40b010]
Actual :<[com.darotapp.cornflix.data.local.database.MovieEntity#3843fe46, com.darotapp.cornflix.data.local.database.MovieEntity#1b40b010]>
The data class for the table is below
Table
#Entity
data class MovieEntity(
var title: String?,
var movieImage:String?,
var rating:Int?,
var overView:String?,
var releaseDate:String?
): Serializable {
operator fun component1(): String? = title
operator fun component2(): String? = movieImage
operator fun component3(): Int? = rating
operator fun component4(): String? = overView
operator fun component5(): String? = releaseDate
#PrimaryKey()
var id: Int = 0
var favourite:Boolean = false
var movieId:String? = ""
}
I finally figured it out. The problem was using IsEqual. I was able to correct this with the code below.
val movies = moviesRepository.getMovies(false, ApplicationProvider.getApplicationContext())
assertEquals(movies?.value, Matchers.equalTo(localTasks))

How to Extract vector in session?

I have saved vector in session and I want to use random value from the vector but dont know how to extract value in session.
Errors:
'httpRequest-6' failed to execute: Vector(437420, 443940, 443932,
437437, 443981, 443956, 443973, 443915, 437445) named 'termIds' does
not support .random function
And
In 2nd scenario It passes vector in get request like this way, http://someurl/api/thr/Vector(435854)/terms/Vector(437420, 443940,
443932, 437437, 443981, 443956, 443973, 443915, 437445)
instead of using
http://someurl/api/thr/435854/terms/443973
::Here is my script::
class getTerm extends Simulation {
val repeatCount = Integer.getInteger("repeatCount", 1).toInt
val userCount = Integer.getInteger("userCount", 1).toInt
val turl = System.getProperty("turl", "some url")
val httpProtocol = http
.baseURL("http://" + turl)
val headers_10 = Map("Content-Type" -> """application/json""")
var thrIds = ""
var termIds = ""
// Scenario - 1
val getTerms = scenario("Scn 1")
.exec(http("list_of_term")
.get("/api/abc")
.headers(headers_10)
.check(jsonPath("$[*].id")
.findAll.saveAs("thrIds"))
)
.exec(http("get_all_terms")
.get("""/api/thr/${thrIds.random()}/terms""")
.headers(headers_10)
.check(jsonPath("$[*].id")
.findAll.saveAs("termIds"))
)
.exec(session => {
thrIds = session("thrIds").as[Long].toString
termIds = session("termIds").as[Long].toString
println("***************************************")
println("Session ====>>>> " + session)
println("Ths ID ====>>>> " + thrIds)
println("Term ID ====>>>> " + termIds)
println("***************************************")
session}
)
// Scenario - 2
// Want to extract vectors here and pass its value into get call
val getKnownTerms = scenario("Get Known Term")
.exec(_.set("thrIds", thrIds))
.exec(_.set("termIds", termIds))
.repeat (repeatCount){
exec(http("get_k_term")
.get("""/api/thr/${thrIds}/terms/${termIds.random()}""")
.headers(headers_10))
}
val scn = List(getTerms.inject(atOnceUsers(1)), getKnownTerms.inject(nothingFor(20 seconds), atOnceUsers(userCount)))
setUp(scn).protocols(httpProtocol)
}
Here is the solution which may help others.
class getTerm extends Simulation {
val repeatCount = Integer.getInteger("repeatCount", 1).toInt
val userCount = Integer.getInteger("userCount", 1).toInt
val turl = System.getProperty("turl", "some url")
val httpProtocol = http
.baseURL("http://" + turl)
val headers_10 = Map("Content-Type" -> """application/json""")
// Change - 1
var thrIds: Seq[String] = _
var termIds: Seq[String] = _
// Scenario - 1
val getTerms = scenario("Scn 1")
.exec(http("list_of_term")
.get("/api/abc")
.headers(headers_10)
.check(jsonPath("$[*].id")
.findAll
.transform { v => thrIds = v; v }
.saveAs("thrIds"))
)
.exec(http("get_all_trms")
.get("""/api/thr/${thrIds.random()}/terms""")
.headers(headers_10)
.check(jsonPath("$[*].id")
.findAll
.transform { v => termIds = v; v }
.saveAs("termIds"))
)
// Scenario - 2
val getKnownTerms = scenario("Get Known Term")
.exec(_.set("thrIds", thrIds))
.exec(_.set("termIds", termIds))
.repeat (repeatCount){
exec(http("get_k_term")
.get("""/api/thr/${thrIds.random()}/terms/${termIds.random()}""")
.headers(headers_10))
}
val scn = List(getTerms.inject(atOnceUsers(1)), getKnownTerms.inject(nothingFor(20 seconds), atOnceUsers(userCount)))
setUp(scn).protocols(httpProtocol)
}

Categories

Resources