Upgrade to Pro — share decks privately, control downloads, hide ads and more …

AndroidデバイスにFTPサーバを建立する

 AndroidデバイスにFTPサーバを建立する

2025/2/12 CA.aab #5の登壇資料です

Yoshihiro WADA

February 11, 2025
Tweet

More Decks by Yoshihiro WADA

Other Decks in Technology

Transcript

  1. { “id”: “@e10dokup”, “name”: “Yoshihiro Wada”, “affiliations”: [ “CyberAgent Inc,

    / Ameba” ], “interested”: [ “camera”, “gadget”, “driving”, “motorsports” ] }
  2. Sony Transfer & Tagging add-on OSS 示 The Apache FtpServer

    Android FTP ppareit/swiftp 見 1 FTP FTP 方 14
  3. Sony Transfer & Tagging add-on OSS 示 The Apache FtpServer

    Android FTP ppareit/swiftp 見 1 FTP FTP 方 16
  4. Jetpack Compose IP ConnectivityManager IP 用 UI 26 private fun

    getCurrentIpAddress(): String { val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager val currentNetwork = connectivityManager.activeNetwork val linkProperties = connectivityManager.getLinkProperties(currentNetwork) return linkProperties?.linkAddresses?.first { it.address is Inet4Address }.toString() }
  5. 曰 LinkProperties IP Android API 行 linkProperties 見 27 Ҿ༻:

    https://developer.android.com/develop/connectivity/network-ops/reading-network-state https://developer.android.com/reference/android/net/LinkProperties#getLinkAddresses()
  6. Activity 用 override Service 用 30 class FtpService : Service()

    { override fun onBind(intent: Intent?): IBinder? { return null } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { // ࣮ࡍʹαʔϏεʹ͍ͤͨ͞ॲཧΛ͜͜ʹهड़͢Δ return START_STICKY } override fun onDestroy() { super.onDestroy() } }
  7. foregroundServiceType Android 14 API 34 色 Data sync Foreground Service

    34 Ҿ༻:https://developer.android.com/develop/background-work/services/fgs/service-types#data-sync
  8. 見 Android Manifest Manifest Foreground Service 言 35 <!-- ݖݶͷ௥Ճ

    --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC"/> <application …> <!-- Foreground Serviceͷએݴ --> <service android:name=".service.FtpService" android:enabled="true" android:exported="false" android:foregroundServiceType=“dataSync"/> … </application>
  9. Service onStartCommand 行 用 ServiceCompat.startForeground 行 用 Foreground Service 37

    Ҿ༻:https://developer.android.com/develop/background-work/services/fgs/launch#promote-service
  10. Foreground Service 用 Foreground Service 38 try { ServiceCompat.startForeground( this,

    ID_FOREGROUND_SERVICE_FTP, createNotification(), // ௨஌Λ࡞Δؔ਺ʢ࣍ϖʔδʣ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC } else { 0 } // ManifestͰએݴͨ͠Foreground Service TypeΛ౰ͯࠐΉ ) // TODO: Foregroundʹग़དྷͨΒ͜͜ͰFTPαʔόΛ࣮ߦ͍ͨ͠ } catch (e: Exception) { Timber.e(e, "Failed to launch foreground service”) }
  11. 用 Foreground Service 39 private fun createNotification(): Notification { val

    channel = NotificationChannel( NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT ) val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager notificationManager.createNotificationChannel(channel) // ௨஌νϟωϧͷઃఆ val notification = NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID).apply { setContentTitle("FTP Server") setContentText("FTP Server established") setSmallIcon(R.drawable.notification_icon) }.build() // ࣮ࡍͷ௨஌ͷੜ੒ return notification }
  12. Activity ForegroundService 行 行 Foreground Service 40 private fun launchFtpService()

    { val intent = Intent(this, FtpService::class.java) startForegroundService(intent) }
  13. Listener UserManager 行 FTP 44 private fun startFtpServer() { //

    Apache FTP ServerͷϑΝΫτϦ val serverFactory = FtpServerFactory() // ϙʔτͳͲΛࢦఆ͢ΔListenerΛ࡞Δ val ftpListener = createFtpListener() // Ϣʔβ໊ɺύεϫʔυΛ؅ཧ͢ΔUserManagerΛ࡞Δ val userManager = createUserManager() // ࡞ͬͨListenerɺUserManagerΛࢦఆ͠ɺFTPαʔόΛ࣮ࡍʹ࡞੒͠ɺ࣮ߦ͢Δ serverFactory.addListener("default", ftpListener) serverFactory.userManager = userManager ftpServer = serverFactory.createServer() ftpServer?.start() }
  14. Listener UserManager 行 FTP 45 private fun startFtpServer() { //

    Apache FTP ServerͷϑΝΫτϦ val serverFactory = FtpServerFactory() // ϙʔτͳͲΛࢦఆ͢ΔListenerΛ࡞Δ val ftpListener = createFtpListener() // Ϣʔβ໊ɺύεϫʔυΛ؅ཧ͢ΔUserManagerΛ࡞Δ val userManager = createUserManager() // ࡞ͬͨListenerɺUserManagerΛࢦఆ͠ɺFTPαʔόΛ࣮ࡍʹ࡞੒͠ɺ࣮ߦ͢Δ serverFactory.addListener("default", ftpListener) serverFactory.userManager = userManager ftpServer = serverFactory.createServer() ftpServer?.start() }
  15. FTP Listener 自 Listener 46 private fun createFtpListener(): Listener {

    val listenerFactory = ListenerFactory() // ࣮ࡍʹ͸Ҿ਺Λड͚औͬͯࢦఆ͢Δͱྑͦ͞͏ listenerFactory.port = <ϙʔτ൪߸> return listenerFactory.createListener() }
  16. Listener UserManager 行 FTP 47 private fun startFtpServer() { //

    Apache FTP ServerͷϑΝΫτϦ val serverFactory = FtpServerFactory() // ϙʔτͳͲΛࢦఆ͢ΔListenerΛ࡞Δ val ftpListener = createFtpListener() // Ϣʔβ໊ɺύεϫʔυΛ؅ཧ͢ΔUserManagerΛ࡞Δ val userManager = createUserManager() // ࡞ͬͨListenerɺUserManagerΛࢦఆ͠ɺFTPαʔόΛ࣮ࡍʹ࡞੒͠ɺ࣮ߦ͢Δ serverFactory.addListener("default", ftpListener) serverFactory.userManager = userManager ftpServer = serverFactory.createServer() ftpServer?.start() }
  17. UserManager 48 private fun createUserManager(): UserManager { val userManagerFactory =

    PropertiesUserManagerFactory() // Ϣʔβ৘ใΛอ؅͢ΔϑΝΠϧͷ࡞੒ val profileFile = File(getExternalFilesDir(null)?.path + "/users.property") if (!profileFile.exists()) { profileFile.createNewFile() } userManagerFactory.file = profileFile userManagerFactory.passwordEncryptor = SaltedPasswordEncryptor() // Ϣʔβ໊ɺύεϫʔυɺݖݶͳͲͷઃఆ val baseUser = BaseUser() baseUser.name = <Ϣʔβ໊> baseUser.password = <ύεϫʔυ> baseUser.homeDirectory = getExternalFilesDir(Environment.DIRECTORY_DCIM)?.path baseUser.authorities = listOf(WritePermission()) val userManager = userManagerFactory.createUserManager() userManager.save(baseUser) return userManager }
  18. Listener UserManager 行 FTP 49 private fun startFtpServer() { //

    Apache FTP ServerͷϑΝΫτϦ val serverFactory = FtpServerFactory() // ϙʔτͳͲΛࢦఆ͢ΔListenerΛ࡞Δ val ftpListener = createFtpListener() // Ϣʔβ໊ɺύεϫʔυΛ؅ཧ͢ΔUserManagerΛ࡞Δ val userManager = createUserManager() // ࡞ͬͨListenerɺUserManagerΛࢦఆ͠ɺFTPαʔόΛ࣮ࡍʹ࡞੒͠ɺ࣮ߦ͢Δ serverFactory.addListener("default", ftpListener) serverFactory.userManager = userManager ftpServer = serverFactory.createServer() ftpServer?.start() }
  19. Foreground Service 行 行 50 try { ServiceCompat.startForeground( this, ID_FOREGROUND_SERVICE_FTP,

    createNotification(), // ௨஌Λ࡞Δؔ਺ʢ࣍ϖʔδʣ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC } else { 0 } // ManifestͰએݴͨ͠Foreground Service TypeΛ౰ͯࠐΉ ) // FTPαʔόͷ࣮ߦ startFtpServer() } catch (e: Exception) { Timber.e(e, "Failed to launch foreground service”) } Cyberduck Android FTP 子