in my android app(media player), i'm scanning all media files in loadingActivity.kt file. and then starting mainActivity.kt. my code is
scanSongs()
intent = Intent(this, MainActivity::class.java)
startActivity(intent)
and my scanSongs() function is
private fun scanSongs() {
val songsJob = async {
val songsFinder = SongsLoader(contentResolver)
songsFinder.load()
songsFinder.getAllSongs()
}
launch {
allSongsList = songsJob.await()
allSongsList?.sortBy { it.getTitle() }
}
}
but before scan complete it is opening mainActivity . and showing empty list . how can i waiting for complete scanSong() , before open mainActivity
Open the MainActivity when you have the allSongsList:
private fun scanSongs() {
val songsJob = async {
val songsFinder = SongsLoader(contentResolver)
songsFinder.load()
songsFinder.getAllSongs()
}
launch {
allSongsList = songsJob.await()
allSongsList?.sortBy { it.getTitle() }
intent = Intent(this, MainActivity::class.java)
startActivity(intent)
}
}
You have to check a condition before start mainactivity.kt that
song list is null or not
Related
In test I want to verify that sendBroadcast been send. Here is the code from view layer requireContext().sendBroadcast(myYntent, myPermission)
And here I am launching the fragment in test
#Test
fun broadcastIntent_test() = runBlocking {
val intent : Intent = Intent()
reactions.emit(WidgetFragmentReaction.BroadcastIntent(intent))
launchFragmentInHiltContainer<WidgetFragment> {
// val context = InstrumentationRegistry.getInstrumentation().targetContext
// val shadow = shadowOf(context)
// val shadowedIntent: Intent = shadow.peekNextStartedActivity()
// maybe some of these might help
}
}
STORY:-
I'm making app like Instagram Reels, with viewPager2 with RecyclerViewAdapter, all functionality working fine,
only one problem I'm facing right now is when I click on comment button the Comment screen is opening in another activity and when I getting back on reels activity after commenting or without commenting,
video playing again and mixing with current audio that means notifyItemChanged is not working properly in my case,
I just want to update that comment count only without affecting whole adapter items.
Class- AdapterClass : RecyclerView.Adapter
onClickListener for Comment button
binding.ivComment.setOnClickListener(View.OnClickListener {
if (Utility.isOnline(context)) {
itemClick(post)
} else {
val toast: Toast = Toast.makeText(
context,
R.string.msg_no_internet,
Toast.LENGTH_SHORT
)
toast.show()
}
})
fun itemClick(postList: PostList?) {
if (Utility.isOnline(context)) {
val intent = Intent(context, BitesCommentActivity::class.java)
intent.putExtra(PostList.SENDEXTRA, postList)
context.startActivity(intent)
} else {
val toast: Toast = Toast.makeText(context, R.string.msg_no_internet, Toast.LENGTH_SHORT)
toast.show()
}
}
Class- Activity Class
Using BroadcastReceiver for update comment count from CommentActivity
private val mMessageReceiver: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val isActivityInForeground = this#BitesSwappableVideosActivity.lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)
if (!isActivityInForeground) {
val message = intent.getStringExtra("message")
val epost_id = intent.extras!!
.getLong(Constant.ScreenExtras.EPOST_ID, -1)
val action = intent.extras!!.getInt(Constant.ScreenExtras.ACTION)
for (i in fav.indices) {
val postList: PostList = fav[i]
val updateIndex: Int
if (action == Constant.COMMENT) {
if (postList.postId == epost_id) {
postList.totalComment = postList.totalComment + 1
eBiteReels_adapter.notifyItemChanged(i)
break
}
}
}
} else {
val message = intent.getStringExtra("message")
val epost_id = intent.extras!!
.getLong(Constant.ScreenExtras.EPOST_ID, -1)
val action = intent.extras!!.getInt(Constant.ScreenExtras.ACTION)
for (i in fav.indices) {
val postList: PostList = fav[i]
if (action == Constant.COMMENT) {
if (postList.postId == epost_id) {
postList.totalComment = postList.totalComment + 1
eBiteReels_adapter.notifyItemChanged(i)
break
}
}
}
}
}
}
I've tried
eBiteReels_adapter.notifyItemChanged(i)
but it cause problem with another items especially with videoplayer.
if I remove notifyItemChanged from my code it refreshes comment count when I restart my SwipableVideoActivity
I implemented a registerForActivityResult in fragment to launch another activity and to get data from the activity. The problem is that the registerForActivityResult sometimes works and sometimes it doesn't. I put a log to be printed and I found that when it works the log is not printed. That means it doesn't go into the function.
val getContent = registerForActivityResult(ActivityResultContracts.StartActivityForResult()){ result:ActivityResult ->
Log.i("register", "out")
if(result.resultCode == Activity.RESULT_OK)
{
val data = result.data
val note = data?.getParcelableExtra<Note>("note")
Log.i("register", "in")
adapter.mNotes[notePos].title = note?.title.toString()
adapter.mNotes[notePos].notes = note?.notes.toString()
adapter.notifyItemChanged(notePos)
}
}
private fun initRecycleView()
{
adapter = NotesAdapter(notesList){note, pos ->
val intent = Intent(this.context, NotingActivity::class.java).apply {
putExtra("note",note)
notePos = pos
}
getContent.launch(intent)
}
rvItems.adapter = adapter
rvItems.layoutManager = GridLayoutManager(this.context, 2)
(rvItems.itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
}
override fun onBackPressed() {
intent.putExtra("note", note)
setResult(Activity.RESULT_OK, intent)
finish()
super.onBackPressed()
}
I am trying to install an app from my fragment. I want the unknown source permission message to be displayed and then the installation process to take place. The problem is that on my first installation, app seems to be crashed.
Of course, next time (when installing another apk) this problem disappears. I did the following steps:
In my viewModel :
fun installApp(uri: Uri) {
viewModelScope.launch(context = exceptionHandler + DEFAULT) {
val promptInstall = Intent(Intent.ACTION_VIEW, uri)
promptInstall.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true)
promptInstall.setDataAndType(uri, "application/vnd.android" + ".package-archive")
promptInstall.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK
promptInstall.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
startActivityMutableLiveData.postValue(promptInstall.toOneTimeEvent())
}
}
and then in my fragment :
viewModel.startActivityLiveData.observe(viewLifecycleOwner, Observer { oneTimeEvent ->
(oneTimeEvent.getValue() as Intent).startActivityFromIntent(requireActivity())})
And finally this is my extension function :
fun Intent.startActivityFromIntent(context: Context) = (context as Activity).startActivity(this)
Well, it seems that the process I mentioned above has a problem(it crashed!) in Android 10 and above. Here is the solution I found:
private fun Uri.installApp(context: Context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (!context.packageManager.canRequestPackageInstalls()) {
startForResult.launch(Intent(ACTION_MANAGE_UNKNOWN_APP_SOURCES))
Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES).setData(
} else {
viewModel.installApp(this)
}
} else {
viewModel.installApp(this)
}
and we must do as below :
private val startForResult =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
when (result.resultCode) {
RESULT_OK -> {
// your logic...
}
RESULT_CANCELED -> {
//do something
}
else -> {
}
}
}
Writing an Android app with Kotlin using Android Studio. I have several activities and each of them has similar buttons. I added global variable ACTID which references each Activity I have through the map.
Every button has android: onClick="onClick" in its XML file.
So, I tried to make a public function:
public fun allClick(view: View){
val context = ACTIVITY_DICT[ACTID]
val toast = Toast.makeText(context, ACTID.toString(), Toast.LENGTH_LONG)
toast.show()
when (view.id)
{
R.id.nextBtn -> {
val intentNext = Intent(context, ACTIVITY_DICT[ACTID+1]!!::class.java)
context?.startActivity(intentNext)
context?.finish()}
R.id.backBtn -> {
val intentBack = Intent(context, ACTIVITY_DICT[ACTID-1]!!::class.java)
context?.startActivity(intentBack)
context?.finish()}
}
}
However, I cannot set allCLick for onClick. How can I fix it? Would be grateful for any possible help.
You can make a base activity BaseActivity, implement allClick(view: View) method in it and inherit from it other activities:
class BaseActivity : AppCompatActivity() {
public fun allClick(view: View) {
val context = ACTIVITY_DICT[ACTID]
val toast = Toast.makeText(context, ACTID.toString(), Toast.LENGTH_LONG)
toast.show()
when (view.id) {
R.id.nextBtn -> {
val intentNext = Intent(context, ACTIVITY_DICT[ACTID+1]!!::class.java)
context?.startActivity(intentNext)
context?.finish()
}
R.id.backBtn -> {
val intentBack = Intent(context, ACTIVITY_DICT[ACTID-1]!!::class.java)
context?.startActivity(intentBack)
context?.finish()
}
}
}
}
Also add android: onClick="allClick" for every button in its XML file.