Jetpack compose with Google Place API - google-places-api

I am trying to use Place SDK with jetpack compose but I can not find any resource on how to implement this.
#Composable
fun PlaceSearchView() {
// Initialize the SDK
Places.initialize(applicationContext, "apiKey")
val placesClient = Places.createClient(this)
}
The above code is based on what is available in the Documentation and I am getting the error
Unresolved reference: applicationContext
My question now: is there a dedicated approach to using google place API in Jetpack Compose?
'this' is not defined in this context

You can use this code to create an intent to launch autocomplete widget as an intent. The code is similar to this
#HiltViewModel
class MyViewModel #Inject constructor(private val myUseCase: MyUseCase, #ApplicationContext applicationContext: Context): ViewModel() {
init {
Places.initialize(applicationContext, "insert api key")
}
val field = listOf(Place.Field.NAME, Place.Field.LAT_LNG)
}
#Composable
fun MyScreen(myViewModel: MyViewModel = hiltViewModel()) {
val context = LocalContext.current
val intent = Autocomplete.IntentBuilder(AutocompleteActivityMode.OVERLAY, exploreViewModel.field).build(context)
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if(it.resultCode == RESULT_OK){
val place = Autocomplete.getPlaceFromIntent(it.data
latLng = place.latLng
Log.d("place LatLng: ", latLng.toString())
// move the camera position of the map
// cameraPositionState.move(CameraUpdateFactory.newLatLngZoom(lonLat, 15f))
}
}
FloatingActionButton(modifier = Modifier
.align(Alignment.TopStart)
.padding(10.dp),
onClick = {
launcher.launch(intent)
}) {
Icon(imageVector = Icons.Default.Search, contentDescription =
"")
}
}

Related

Call jetpack compose from companion object with context

I want to try Jetpack Compose and I encountered with issues.
Can I call composable from companion object?
companion object {
fun showDialog(context: Context){
ComposeView(context = context).apply {
setContent { //isAttachedToWindow = false
CustomDialog(progressIndicator = false) //custom dialog with #Composable
}
}
}
}
And additional question: Should I need ModelView class for logic which create data for this CustomDialog and catch callback from this dialog?

Broadcast Extension with ReplayKit Xamarin iOS not displaying device screen

I created a Xamarin forms project and added Broadcast Upload Extension and Extension UI and reference them into IOS Project also I followed the instructions in the doc here
https://learn.microsoft.com/en-us/xamarin/ios/platform/extensions#container-app-project-requirements
I uses agora for screen sharing but the result is the device share the camera instead of it's screen
I followed this sample
https://github.com/DreamTeamMobile/Xamarin.Agora.Samples/tree/master/ScreenSharing
and added a Dependency service Interface to invoke it from Xamarin forms all is working expect device share it's camera not it's screen
public class AgoraServiceImplementation : IAgoraService
{
private void JoiningCompleted(Foundation.NSString arg1, nuint arg2, nint arg3)
{
_myId = arg2;
_agoraEngine.SetEnableSpeakerphone(true);
JoinChannelSuccess((uint)_myId);
var bundle = NSBundle.MainBundle.GetUrlForResource("ScreenSharingIOSExtension", "appex", "PlugIns");
var frame = new CGRect(100, 100, 60, 60);
var broadcastPicker = new RPSystemBroadcastPickerView(frame);
var bundle2 = new NSBundle(bundle);
broadcastPicker.PreferredExtension = bundle2.BundleIdentifier;
var vc = Platform.GetCurrentUIViewController();
vc.Add(broadcastPicker);
}
public void StartShareScreen(string sessionId, string agoraAPI, string token, VideoAgoraProfile profile = VideoAgoraProfile.Portrait360P, bool swapWidthAndHeight = false, bool webSdkInteroperability = false)
{
_agoraDelegate = new AgoraRtcDelegate(this);
_agoraEngine = AgoraRtcEngineKit.SharedEngineWithAppIdAndDelegate(agoraAPI, _agoraDelegate);
_agoraEngine.EnableWebSdkInteroperability(webSdkInteroperability);
_agoraEngine.SetChannelProfile(ChannelProfile.LiveBroadcasting);
_agoraEngine.SetClientRole(ClientRole.Broadcaster);
//
_agoraEngine.EnableVideo();
if (!string.IsNullOrEmpty(AgoraSettings.Current.EncryptionPhrase))
{
_agoraEngine.SetEncryptionMode(AgoraSettings.Current.EncryptionType.GetModeString());
_agoraEngine.SetEncryptionSecret(helper.AgoraSettings.Current.EncryptionPhrase);
}
_agoraEngine.StartPreview();
Join();
}
private async void Join()
{
var token = await AgoraTokenService.GetRtcToken(helper.AgoraSettings.Current.RoomName);
if (string.IsNullOrEmpty(token))
{
//smth went wrong
}
else
{
_agoraEngine.JoinChannelByToken(token, AgoraSettings.Current.RoomName, null, 0, JoiningCompleted);
}
}
}
any help ?

Tornadofx: Trying to reload/refresh MainView

I've only really just started on Tornadofx and was having a bit of trouble trying to figure out how to reload a view so the controls in that view are refreshed.
Below is a simplified version of the code I'm working with. I've got a loop to generate radio-button controls based on strings in a list.
class MainView: View("MainView") {
override val root = vbox {
for(x in radioText) {
radiobutton(x, radioGroup) {
action {
radioSelected = this#radiobutton.text
}
}
}
button("Next") {
action {
// Reload View to update radiobuttons with new values
}
}
}
}
In the program I need to go through several sets of these radio buttons, and so the idea was that each time the user presses the "Next" button, the items in the radioText list would be updated to match the next set of radio-buttons. Then I was looking for a way to get the view to update with these new values.
I tried using openWindow() to open a new instance of the view, but then when I used close() to get rid of the previous instance and ended up closing both windows.
button("Next") {
action {
MainView().openWindow()
close()
}
}
Any help with this would be much appreciated,
Thanks.
If I understood correctly, you are trying to have a list of string and generate radiobuttons with it. So, by adding the variables to your example, would be something like this:
class MainView: View("MainView") {
val radioText = ArrayList<String>()
var radioGroup : ToggleGroup by singleAssign()
lateinit var radioSelected : String
override val root = vbox {
radioText.addAll(arrayListOf("One","Two","Three","Four"))
radioGroup = togglegroup(){}
for(x in radioText) {
radiobutton(x,radioGroup) {
action {
radioSelected = text //You don't need this#radiobutton.text
}
}
}
button("Next") {
action {
// Reload View to update radiobuttons with new values
}
}
}
}
I thing is a better idea having your radiobutton created by a listview, wich would be updated by a observable list of string, like I do bellow:
class MainView2: View("MainView") {
// this is a list of observable string, so when the items on his list change
// the listview is updated
val radioText = FXCollections.observableArrayList<String>()
var radioGroup : ToggleGroup by singleAssign()
lateinit var radioSelected : String
override val root = vbox() {
prefWidth = 200.0
prefHeight = 300.0
radioText.setAll("One","Two","Three","Four")
radioGroup = togglegroup(){}
listview<String>(radioText){
// Setting listview height dinamically
fixedCellSize = 25.0
prefHeightProperty().bind(radioText.sizeProperty.multiply(fixedCellSizeProperty().add(2)))
// Generating the radiobutton acording to strings on radioText
cellFormat {
graphic = cache(it){
radiobutton(it,radioGroup){
action {
radioSelected = text
}
}
}
}
}
button("Next") {
action {
radioText.clear()
radioText.setAll("Five","Six","Seven","Eight","Nine","Ten")
}
}
}
}
Please let me know if there is something you don't understand on my aproach.

Using Android vibrator seems a bit slow, what's a good strategy?

I am trying to make a relatively simple game in Kotlin with force feedback. Every time an object hits a wall I want the phone to vibrate.
Here is my code, which generally works:
val vibT = 0L
val vibrator: Vibrator by lazy {
getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
}
and then:
fun bump() {
var now = System.currentTimeMillis()
if ( vibrator.hasVibrator() && now>vibT+51) {
vibrator.cancel()
vibrator.vibrate(VibrationEffect.createOneShot(50, VibrationEffect.DEFAULT_AMPLITUDE))
vibT = now
}
}
It seems that when the code runs the bump() function in rapid succession (for example, when several objects hit the wall), it gets rather sluggish with the redraws. If I comment out the line vibrator.vibrate(...) then the game runs smoothly.
At first, I thought maybe I was just trying to call the function while it was still vibrating, hence causing a backlog of vibration requests, but even after adding in the timing check with now and vibT it's still a bit sluggish when a lot of calls are made to the function.
I'm assuming this is not a synchronous call, and that the code continues executing as soon as I've requested a vibration, but I can't find documentation to back that up.
Is there a better strategy? Maybe there are some gotcha's that I ought to be aware of when doing this?
After testing, I saw that calls to Vibrator::vibrate can take up to 5 milliseconds. If you're doing it in rapid succession, this can cause slowdown, as in your case.
I wrote a helper class that moves the calls to Vibrator::vibrate to a background thread to avoid blocking the UI thread:
import android.content.Context
import android.os.Build
import android.os.VibrationEffect
import android.os.Vibrator
import java.util.concurrent.ArrayBlockingQueue
/**
* #author https://github.com/gottagofaster236
*/
class AsyncVibrator(context: Context) {
private val vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
private val vibrationRequestsQueue = ArrayBlockingQueue<Long>(VIBRATOR_QUEUE_CAPACITY)
private var vibrationThread: Thread? = null
fun vibrate(lengthMs: Long) {
vibrationRequestsQueue.offer(lengthMs)
}
fun start() {
stop()
vibrationThread = Thread(::processVibrationRequests).apply(Thread::start)
}
fun stop() {
vibrationThread?.interrupt()
vibrationThread = null
}
private fun processVibrationRequests() {
while (!Thread.currentThread().isInterrupted) {
val lengthMs = try {
vibrationRequestsQueue.take()
} catch (e: InterruptedException) {
break
}
if (Build.VERSION.SDK_INT >= 26) {
vibrator.vibrate(
VibrationEffect.createOneShot(
lengthMs,
VibrationEffect.DEFAULT_AMPLITUDE
)
)
} else {
#Suppress("DEPRECATION")
vibrator.vibrate(lengthMs)
}
}
}
private companion object {
const val VIBRATOR_QUEUE_CAPACITY = 10
}
}
Usage in an Activity:
// import ...
class MainActivity : Activity() {
private val asyncVibrator = AsyncVibrator(this)
// ...
override fun onResume() {
super.onResume()
asyncVibrator.start()
}
override fun onPause() {
asyncVibrator.stop()
super.onPause()
}
fun testVibration() {
// Vibrate for 100 milliseconds.
asyncVibrator.vibrate(100L)
}
}
Try this.
// this initiates the android vibrator [ put this on the onCreate ]
val vibe = this#MainActivity.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
then
// put this where you want the vibrator to activate (fun bump*())
val vibratorService = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
vibratorService.vibrate(40)

NativeScript Angular: registerElement of custom component with attributes

I want to integrate a custom NS core / third party component into an Angular template. The attributes of my component should also be set in the template.
Given the generated sample from tns, i have done the following steps:
Register my Component:
registerElement("TestView", () => require("./test-view").TestView);
Create Component:
import observable = require("data/observable");
import stackLayout = require("ui/layouts/stack-layout");
import label = require("ui/label");
import button = require("ui/button");
import { View } from "ui/core/view";
import { Property, PropertyChangeData, PropertyMetadata, PropertyMetadataSettings } from "ui/core/dependency-observable";
export class TestView extends stackLayout.StackLayout {
public static userNameProperty = new Property(
"userName",
"TestView",
new PropertyMetadata("", PropertyMetadataSettings.None)
);
public get userName(): string {
return this._getValue(TestView.userNameProperty);
}
public set userName(newName: string) {
this._setValue(TestView.userNameProperty, newName);
}
constructor() {
super();
var counter: number = 0;
var lbl = new label.Label();
var btn = new button.Button();
btn.text = "Tap me " + this.userName + "!";
btn.on(button.Button.tapEvent, (args: observable.EventData) => {
lbl.text = "Tap " + counter++;
});
this.addChild(lbl);
this.addChild(btn);
}
}
Use it in Angular template:
<StackLayout class="p-20">
<TestView userName="Felix"></TestView>
</StackLayout>
The component displays, but the button text does not show "Tap me [userName]", because userName is undefined.
What is the correct way to pass arguments as attributes for the component?
Update
Having read Data Binding and Properties, i augmented above code sample with definition of a userName property. But its still not set, quite frustrating...
Can anybody give some insight? Many thanks.
Finally got it working.
There has to be established Data Binding between
Angular template and custom Component TestView by encapsulating the property userName in a Property type of the ui/core/dependency-observable module (see above code).
the component and it's button by binding the component's userName source property to the button target text property (you can also set this by a default BindingContext).
var btn = new button.Button();
var buttonBindingOptions = {
expression: "'Tap me ' + userName + '!'",
sourceProperty: "userName",
targetProperty: "text",
twoWay: false
};
btn.bind(buttonBindingOptions, this);
In the parent Appcomponent user can by dynamically set like this:
app.component.ts:
export class AppComponent {
user : string;
constructor() {
this.user = "Felix";
setTimeout(()=> {this.user = "Other"}, 1000);
}
}
app.html:
<TestView [userName]="user"></TestView>

Resources