@@ -44,7 +44,6 @@ class MainActivity : Activity() {
4444 super .onCreate(savedInstanceState)
4545 setContentView(R .layout.activity_main)
4646
47- // UI 接続
4847 txtUsername = findViewById(R .id.txtUsername)
4948 btnSelect = findViewById(R .id.btnSelect)
5049 btnUpload = findViewById(R .id.btnUpload)
@@ -105,7 +104,10 @@ class MainActivity : Activity() {
105104
106105 scope.launch {
107106 val skinBitmap = fetchMinecraftSkin(mcToken)
108- val bmp = resizeTo64(skinBitmap ? : Bitmap .createBitmap(64 , 64 , Bitmap .Config .ARGB_8888 ).apply { eraseColor(0xFFFF0000 .toInt()) })
107+ val bmp = resizeTo64(
108+ skinBitmap ? : Bitmap .createBitmap(64 , 64 , Bitmap .Config .ARGB_8888 )
109+ .apply { eraseColor(0xFFFF0000 .toInt()) }
110+ )
109111 currentSkinBitmap = bmp
110112 skinView.setImageBitmap(bmp)
111113 }
@@ -189,67 +191,75 @@ class MainActivity : Activity() {
189191 }
190192
191193 progressBar.visibility = View .GONE
192- Toast .makeText(this @MainActivity,
194+ Toast .makeText(
195+ this @MainActivity,
193196 if (success) " アップロード完了" else " アップロード失敗" ,
194- Toast .LENGTH_SHORT ).show()
197+ Toast .LENGTH_SHORT
198+ ).show()
195199 }
196200 }
197201
198- private suspend fun uploadSkin (token : String , bmp : Bitmap , model : String , onProgress : (Int ) -> Unit ): Boolean =
199- withContext(Dispatchers .IO ) {
200- try {
201- val boundary = " ----RabimiSkinBoundary"
202- val url = URL (" https://api.minecraftservices.com/minecraft/profile/skins" )
203- val conn = url.openConnection() as HttpURLConnection
204- conn.doOutput = true
205- conn.requestMethod = " POST"
206- conn.setRequestProperty(" Authorization" , " Bearer $token " )
207- conn.setRequestProperty(" Content-Type" , " multipart/form-data; boundary=$boundary " )
208- conn.connectTimeout = 15000
209- conn.readTimeout = 15000
210-
211- val baos = ByteArrayOutputStream ()
212- baos.write(" --$boundary \r\n " .toByteArray())
213- baos.write(" Content-Disposition: form-data; name=\" model\"\r\n\r\n $model \r\n " .toByteArray())
214- baos.write(" --$boundary \r\n " .toByteArray())
215- baos.write(" Content-Disposition: form-data; name=\" file\" ; filename=\" skin.png\"\r\n " .toByteArray())
216- baos.write(" Content-Type: image/png\r\n\r\n " .toByteArray())
217-
218- val skinBytes = ByteArrayOutputStream ()
219- bmp.compress(Bitmap .CompressFormat .PNG , 100 , skinBytes)
220- val byteArray = skinBytes.toByteArray()
221- val chunkSize = if (byteArray.size >= 100 ) byteArray.size / 100 else byteArray.size
222-
223- if (chunkSize <= 0 ) {
224- baos.write(byteArray)
225- onProgress(100 )
226- } else {
227- for (i in 0 until 100 ) {
228- val start = i * chunkSize
229- val end = if (i == 99 ) byteArray.size else (i + 1 ) * chunkSize
230- if (start >= byteArray.size) break
231- baos.write(byteArray, start, end - start)
232- onProgress(i + 1 )
233- }
202+ private suspend fun uploadSkin (
203+ token : String ,
204+ bmp : Bitmap ,
205+ model : String , // slim / classic
206+ onProgress : (Int ) -> Unit
207+ ): Boolean = withContext(Dispatchers .IO ) {
208+ try {
209+ val boundary = " ----RabimiSkinBoundary"
210+ val url = URL (" https://api.minecraftservices.com/minecraft/profile/skins" )
211+ val conn = url.openConnection() as HttpURLConnection
212+ conn.doOutput = true
213+ conn.requestMethod = " POST"
214+ conn.setRequestProperty(" Authorization" , " Bearer $token " )
215+ conn.setRequestProperty(" Content-Type" , " multipart/form-data; boundary=$boundary " )
216+ conn.connectTimeout = 15000
217+ conn.readTimeout = 15000
218+
219+ val out = DataOutputStream (conn.outputStream)
220+
221+ // 正式なキーは "variant"
222+ out .writeBytes(" --$boundary \r\n " )
223+ out .writeBytes(" Content-Disposition: form-data; name=\" variant\"\r\n\r\n " )
224+ out .writeBytes(" $model \r\n " )
225+
226+ // PNG ファイルのアップロード
227+ out .writeBytes(" --$boundary \r\n " )
228+ out .writeBytes(" Content-Disposition: form-data; name=\" file\" ; filename=\" skin.png\"\r\n " )
229+ out .writeBytes(" Content-Type: image/png\r\n\r\n " )
230+
231+ val pngBaos = ByteArrayOutputStream ()
232+ bmp.compress(Bitmap .CompressFormat .PNG , 100 , pngBaos)
233+ val bytes = pngBaos.toByteArray()
234+
235+ val chunk = if (bytes.size >= 100 ) bytes.size / 100 else bytes.size
236+ if (chunk <= 0 ) {
237+ out .write(bytes)
238+ onProgress(100 )
239+ } else {
240+ for (i in 0 until 100 ) {
241+ val start = i * chunk
242+ val end = if (i == 99 ) bytes.size else (i + 1 ) * chunk
243+ if (start >= bytes.size) break
244+ out .write(bytes, start, end - start)
245+ onProgress(i + 1 )
234246 }
247+ }
235248
236- baos.write(" \r\n --$boundary --\r\n " .toByteArray())
237- val out = DataOutputStream (conn.outputStream)
238- out .write(baos.toByteArray())
239- out .flush()
240- out .close()
249+ out .writeBytes(" \r\n --$boundary --\r\n " )
250+ out .flush()
251+ out .close()
241252
242- conn.inputStream.use { it.readBytes() }
243- val rc = conn.responseCode
244- rc in 200 .. 299
245- } catch (e: Exception ) {
246- e.printStackTrace()
247- false
248- }
253+ val rc = conn.responseCode
254+ rc in 200 .. 299
255+ } catch (e: Exception ) {
256+ e.printStackTrace()
257+ false
249258 }
259+ }
250260
251261 override fun onDestroy () {
252262 super .onDestroy()
253263 scope.cancel()
254264 }
255- }
265+ }
0 commit comments