Development record of developer who study hard everyday.

,

Text-To-Speech(TTS) not worked above Android 13

 Text-To-Speech(TTS) not worked above Android 13

Android development blog


Text-to-speech(TTS) is the underlying software used by screen readers when they convert text into spoken content..

However, you can not have TTS service basically from Android 13.

You must take action following below guide.

  1. Open your device Settings .
  2. Select Accessibility and then Text-to-speech output.
  3. Choose your preferred engine, language, speech rate, and pitch.
    • The default text-to-speech engine choices vary by device. Options can include Google's Text-to-speech engine, the device manufacturer's engine, and any third-party text-to-speech engines that you've downloaded from the Google Play Store.





Share:
Read More
,

Variety of Stream in Java(자바 스트림 종류)

Variety of Stream in Java

자바 스트림 종류

Android development blog


종류IO 대상 기준자료의 종류 기준스트림의 기능 기준
FileInputStream입력 스트림바이트 단위기반 스트림
FileReader입력 스트림문자 단위기반 스트림
BufferedInputStream입력 스트림바이트 단위보조 스트림
BufferedReader입력 스트림문자 단위보조 스트림
FileOutputStream출력 스트림바이트 단위기반 스트림
FileWriter출력 스트림문자 단위기반 스트림
BufferedOutputStream출력 스트림바이트 단위보조 스트림
BufferedWriter출력 스트림문자 단위보조 스트림


✊ 문자 기반 스트림

자바의 Char 형은 2 byte를 사용하는데, 바이트 단위는 입출력 단위가 1 byte이므로 문자를 처리하기 어려웠다.

이를 보완하기 위해 등장한 것이 바로 문자 기반 스트림이다.


✋ 보조 스트림

기반 스트림은 대상에 직접 자료를 읽고 쓰는 기능의 스트림이다.

보토 스트림은 스트림의 기능을 향상시키거나 새로운 기능을 추가할 수 있는 스트림을 말한다.

오로지 보완하는 용도이기에 실제데이터를 주고 받지 않고, 데이터를 입출력하는 기능은 없다.

따라서 스트림을 먼저 생성한 후, 보조 스트림을 생성하여 사용한다.


출처: 여기











Share:
Read More
,

Get Uri from android drawable resource

 Get Uri from android drawable resource

Android development blog

1. What I have in my android drawable folder

android project drawable folder


2. Get Uri from drawable

val imgResourceId = context.resources.getIdentifier("album" + song.image.substringBefore("."), "drawable", context.packageName)
val imageUri = Uri.Builder().scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
.authority(context.resources.getResourcePackageName(imgResourceId))
.appendPath(context.resources.getResourceTypeName(imgResourceId))
.appendPath(context.resources.getResourceEntryName(imgResourceId))
.build()


3. Result

android.resource://net.twobeone.battlesinger/drawable/album00290

android.resource://net.twobeone.battlesinger/drawable/album01468

android.resource://net.twobeone.battlesinger/drawable/album49492


Share:
Read More
, , ,

SideEffect in Android Composable(collectAsStateWithLifecycle, LaunchedEffect, rememberCoroutineScope)

 SideEffect in Android Composable


Android developer blog

✋✋✋ SideEffect

A side-effect in Compose is a change to the state of the app that happens outside the scope of a composable function.

For example, opening a new screen when the user taps on a button, or showing a message when the app doesn't have Internet connection.


1. collectAsStateWithLifecycle

dependencies {
implementation "androidx.lifecycle:lifecycle-runtime-compose:2.6.0"
}

First, add dependency of "androidx.lifecycle:lifecycle-runtime-compose"


@OptIn(ExperimentalMaterialApi::class)
@Composable
fun CraneHomeContent(
onExploreItemClicked: OnExploreItemClicked,
openDrawer: () -> Unit,
modifier: Modifier = Modifier,
viewModel: MainViewModel = viewModel(),
) {
// TODO Codelab: collectAsStateWithLifecycle step - consume stream of data from the ViewModel
// val suggestedDestinations: List<ExploreModel> = remember { emptyList() }
val suggestedDestinations by viewModel.suggestedDestinations.collectAsStateWithLifecycle()

val onPeopleChanged: (Int) -> Unit = { viewModel.updatePeople(it) }
var tabSelected by remember { mutableStateOf(CraneScreen.Fly) }

BackdropScaffold(
modifier = modifier,
scaffoldState = rememberBackdropScaffoldState(BackdropValue.Revealed),
frontLayerScrimColor = Color.Unspecified,
appBar = {
HomeTabBar(openDrawer, tabSelected, onTabSelected = { tabSelected = it })
},
backLayerContent = {
SearchContent(
tabSelected,
viewModel,
onPeopleChanged
)
},
frontLayerContent = {
when (tabSelected) {
CraneScreen.Fly -> {
ExploreSection(
title = "Explore Flights by Destination",
exploreList = suggestedDestinations,
onItemClicked = onExploreItemClicked
)
}
CraneScreen.Sleep -> {
ExploreSection(
title = "Explore Properties by Destination",
exploreList = viewModel.hotels,
onItemClicked = onExploreItemClicked
)
}
CraneScreen.Eat -> {
ExploreSection(
title = "Explore Restaurants by Destination",
exploreList = viewModel.restaurants,
onItemClicked = onExploreItemClicked
)
}
}
}
)
}

Second, in CrameHomeContent composable, you can consume the list of destinations as form of state using collectAsstateWithLifecycle() method.


💪💪💪 Compose also offers APIs for Android's most popular stream-based solutions:

- LiveData.observeAsState() in "androidx.compose.runtime:runtime-livedata"

- Observable.subscribeAsState() in "androidx.compose.runtime:runtime-rxjava2"


2. LaunchedEffect and rememberUpdatedState

To call suspend functions safely from inside a composable, use the LaunchedEffect API, which triggers a coroutine scoped side-effect in Compose.

When LaunchedEffect enters the Composition, it launches a coroutine with the block of code passed as a key parameter.

The coroutine will be canceled if LaunchedEffect leaves the composition.


LaunchedEffect take a variable number of keys as a parameter that are used to restart the effect whenever one of those keys changes.

@Composable
fun LandingScreen(onTimeout: () -> Unit, modifier: Modifier = Modifier) {
Box(modifier = modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
val currentOnTimeOut by rememberUpdatedState(onTimeout)    //1

LaunchedEffect(key1 = Unit) {    //2
delay(SplashWaitTime)
onTimeout.invoke()
}
Image(painterResource(id = R.drawable.ic_crane_drawer), contentDescription = null)
}
}

1 => The rememberUpdatedState() make us refer to the latest onTimeout function that LandingScreen was recomposed with

2 => Create an coroutine scope that matches the lifecycle of LandingScreen.

Because the key parameter is Unit that is not changed, the delay shouldn't start again.


3. rememberCoroutineScope

API to open the navigation drawer is suspend function.

How do we call suspend function in callback function?

@Composable
fun CraneHome(
onExploreItemClicked: OnExploreItemClicked,
modifier: Modifier = Modifier,
) {
val scaffoldState = rememberScaffoldState()
Scaffold(
scaffoldState = scaffoldState,
modifier = Modifier.statusBarsPadding(),
drawerContent = {
CraneDrawer()
}
) { padding ->
val scope = rememberCoroutineScope()
CraneHomeContent(
modifier = modifier.padding(padding),
onExploreItemClicked = onExploreItemClicked,
openDrawer = {
scope.launch {
scaffoldState.drawerState.open()
}
}
)
}
}

We want a CoroutineScope that follows the lifecycle of its call-site.

The rememberCoroutineScope API returns a CoroutineScope bound to the point in the Composition where you call it.

The scope will be automatically canceled once it leaves the Composition.


✊✊✊ LaunchedEffect vs rememberCoroutineScope

Using LauncedEffect is not possible to use in regular callback which is outside of the Composition.

Both can produce CoroutineScope but, LaunchedEffect can control when the side-effect would be called.


Share:
Read More
,

Study Git reset

 Study Git reset


1. Initial State

Initial git state


2. git reset --soft 8d553fd

result after git reset --soft

Current file is represented at "Add text 'c'"


Staging area after git reset --soft

Staging area has commit about "Add text 'c'"


3. git reset --mixed 8d553fd


current file after git reset --mixed

Current file is represented at "Add text 'c'"


Staging area after git reset --mixed

"git reset --mixed" empty staging area

"add command" is canceled.



4. git reset --hard 8d553fd


Current file after git reset --hard

Current file is represented at "Add text 'a'"


Staging area after git reset --hard

"git reset --mixed" empty staging area

"add command" is canceled.



++) Image reference about reset


git reset --soft image description

git reset --mixed image description























Share:
Read More