我嘗試按照此示例創建和使用 BoundService:https : //developer.android.com/guide/components/bound-services#Binder
問題是,它不會為我連接到服務。我有一個現有專案,其中包含一些片段內容,但以防萬一這搞砸了,我也復制了它。那是我的 MainActivity.kt:
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.IBinder
import android.util.Log
import android.view.MenuItem
import android.view.View
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.drawerlayout.widget.DrawerLayout
import androidx.fragment.app.Fragment
import com.google.android.material.navigation.NavigationView
import com.google.android.material.tabs.TabLayout
class MainActivity : AppCompatActivity() {
lateinit var toggle : ActionBarDrawerToggle
lateinit var drawerLayout: DrawerLayout
private lateinit var mService: LocalService
private var mBound: Boolean = false
/** Defines callbacks for service binding, passed to bindService() */
private val connection = object : ServiceConnection {
override fun onServiceConnected(className: ComponentName, service: IBinder) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
Log.w("test", "test")
val binder = service as LocalService.LocalBinder
mService = binder.getService()
mBound = true
}
override fun onServiceDisconnected(arg0: ComponentName) {
mBound = false
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
drawerLayout = findViewById(R.id.drawerLayout)
val navView : NavigationView = findViewById(R.id.nav_view)
toggle = ActionBarDrawerToggle(this, drawerLayout, R.string.open, R.string.close)
drawerLayout.addDrawerListener(toggle)
toggle.syncState()
supportActionBar?.setDisplayHomeAsUpEnabled(true)
navView.setNavigationItemSelectedListener {
// Highlight the current selected Item
it.isChecked = true
// Switch Fragments when user clicks on Items in NavDrawer
when(it.itemId) {
R.id.nav_home -> replaceFragment(HomeFragment(), it.title.toString())
R.id.nav_import -> replaceFragment(ImportFragment(), it.title.toString())
R.id.nav_export -> replaceFragment(ExportFragment(), it.title.toString())
R.id.nav_share -> replaceFragment(ShareFragment(), it.title.toString())
}
true
}
// Default Page is Home
replaceFragment(HomeFragment(), "Home")
}
// Method for replacing fragments
private fun replaceFragment(fragment: Fragment, title : String) {
val fragmentManager = supportFragmentManager
val fragmentTransaction = fragmentManager.beginTransaction()
fragmentTransaction.replace(R.id.frameLayout, fragment)
fragmentTransaction.commit()
// Close Drawer when user clicks on it
drawerLayout.closeDrawers()
// Set the correct title of current fragment
setTitle(title)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if(toggle.onOptionsItemSelected(item)) {
return true
}
return super.onOptionsItemSelected(item)
}
override fun onStart() {
super.onStart()
// Bind to LocalService
Intent(this, LocalService::class.java).also { intent ->
bindService(intent, connection, Context.BIND_AUTO_CREATE)
}
}
override fun onStop() {
super.onStop()
unbindService(connection)
mBound = false
}
/** Called when a button is clicked (the button in the layout file attaches to
* this method with the android:onClick attribute) */
fun onButtonClick(v: View) {
if (mBound) {
// Call a method from the LocalService.
// However, if this call were something that might hang, then this request should
// occur in a separate thread to avoid slowing down the activity performance.
val num: Int = mService.randomNumber
Toast.makeText(this, "number: $num", Toast.LENGTH_SHORT).show()
}
}
}
帶有 onButtonClick 偵聽器的 Button 位于 Home Fragment 中并正確呼叫該函式(我假設例如帶有 testmessage 的 Toast 然后被顯示)。但是,mBound 始終保持值“false”,因此 onButtonClick 函式什么也不做。我的錯誤在哪里?
為了使它完整,那就是 LocalService.kt:
import android.app.Service
import android.content.Intent
import android.os.Binder
import android.os.IBinder
import java.util.*
class LocalService : Service() {
// Binder given to clients
private val binder = LocalBinder()
// Random number generator
private val mGenerator = Random()
/** method for clients */
val randomNumber: Int
get() = mGenerator.nextInt(100)
/**
* Class used for the client Binder. Because we know this service always
* runs in the same process as its clients, we don't need to deal with IPC.
*/
inner class LocalBinder : Binder() {
// Return this instance of LocalService so clients can call public methods
fun getService(): LocalService = this@LocalService
}
override fun onBind(intent: Intent): IBinder {
return binder
}
}
uj5u.com熱心網友回復:
您是否在 Android 清單檔案中宣告了該服務?嘗試在您的活動中使用 getApplicationContext().bindService 而不是 bindService 。它使用更高級別的應用程式背景關系。我希望能幫到你。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/388696.html
