Skip to content

Commit f3fc6a9

Browse files
authored
MainActivity.kt の更新
1 parent adb1e8f commit f3fc6a9

File tree

1 file changed

+64
-57
lines changed

1 file changed

+64
-57
lines changed

app/src/main/java/com/rabimi/javaskinchanger/MainActivity.kt

Lines changed: 64 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import android.graphics.Bitmap
77
import android.graphics.BitmapFactory
88
import android.os.Bundle
99
import android.provider.MediaStore
10+
import android.util.Log
1011
import android.view.View
1112
import android.widget.*
1213
import androidx.appcompat.app.AlertDialog
@@ -19,7 +20,7 @@ import java.net.URL
1920

2021
class MainActivity : Activity() {
2122

22-
companion object { private const val TAG = "SkinDebug" }
23+
companion object { private const val TAG = "SkinUpload" }
2324

2425
private lateinit var txtUsername: TextView
2526
private lateinit var btnSelect: Button
@@ -55,27 +56,24 @@ class MainActivity : Activity() {
5556

5657
setupUI()
5758
checkLogin()
58-
59-
// ★ 初期スキンは res/raw/steve.png
6059
loadDefaultSteveSkin()
6160
}
6261

63-
/** res/raw/steve.png を読み込む */
64-
private fun loadDefaultSteveSkin() {
65-
val input = resources.openRawResource(R.raw.steve)
66-
val bmp = BitmapFactory.decodeStream(input)
67-
val resized = resizeTo64(bmp)
68-
69-
currentSkinBitmap = resized
70-
skinView.setImageBitmap(resized)
71-
}
72-
7362
private fun setupUI() {
7463
btnSelect.backgroundTintList = ColorStateList.valueOf(colorSelect)
7564
btnUpload.backgroundTintList = ColorStateList.valueOf(colorUploadInitial)
7665
btnUpload.visibility = View.GONE
7766
progressBar.visibility = View.GONE
7867

68+
// ★ 文字を白色に統一
69+
val white = getColor(R.color.white)
70+
txtUsername.setTextColor(white)
71+
lblModel.setTextColor(white)
72+
btnSelect.setTextColor(white)
73+
btnUpload.setTextColor(white)
74+
btnLibrary.setTextColor(white)
75+
btnLogout.setTextColor(white)
76+
7977
switchModel.setOnCheckedChangeListener { _, isChecked ->
8078
lblModel.text = if (isChecked) "モデル: Alex" else "モデル: Steve"
8179
}
@@ -84,10 +82,7 @@ class MainActivity : Activity() {
8482
btnUpload.setOnClickListener { handleUpload() }
8583

8684
btnLibrary.setOnClickListener {
87-
AlertDialog.Builder(this)
88-
.setMessage("未実装")
89-
.setPositiveButton("OK", null)
90-
.show()
85+
AlertDialog.Builder(this).setMessage("未実装").setPositiveButton("OK", null).show()
9186
}
9287

9388
btnLogout.setOnClickListener {
@@ -97,10 +92,19 @@ class MainActivity : Activity() {
9792
}
9893
}
9994

95+
/** res/raw/steve.png 読み込み */
96+
private fun loadDefaultSteveSkin() {
97+
val input = resources.openRawResource(R.raw.steve)
98+
val bmp = BitmapFactory.decodeStream(input)
99+
currentSkinBitmap = resizeTo64(bmp)
100+
skinView.setImageBitmap(currentSkinBitmap)
101+
}
102+
100103
private fun checkLogin() {
101-
val prefs = getSharedPreferences("prefs", MODE_PRIVATE)
102-
val username = prefs.getString("minecraft_username", null)
103-
val token = prefs.getString("minecraft_token", null)
104+
val p = getSharedPreferences("prefs", MODE_PRIVATE)
105+
val username = p.getString("minecraft_username", null)
106+
val token = p.getString("minecraft_token", null)
107+
104108
if (username == null || token == null) {
105109
startActivity(Intent(this, WelcomeActivity::class.java))
106110
finish()
@@ -109,7 +113,6 @@ class MainActivity : Activity() {
109113
}
110114
}
111115

112-
/** ファイル選択 */
113116
private fun selectSkinImage() {
114117
val intent = Intent(Intent.ACTION_GET_CONTENT).apply { type = "image/*" }
115118
startActivityForResult(Intent.createChooser(intent, "スキンを選択"), REQUEST_SKIN_PICK)
@@ -119,7 +122,6 @@ class MainActivity : Activity() {
119122
super.onActivityResult(req, res, data)
120123
if (req == REQUEST_SKIN_PICK && res == Activity.RESULT_OK) {
121124
val uri = data?.data ?: return
122-
123125
try {
124126
val orig = MediaStore.Images.Media.getBitmap(contentResolver, uri)
125127
val bmp = resizeTo64(orig)
@@ -133,8 +135,7 @@ class MainActivity : Activity() {
133135
} catch (e: Exception) {
134136
e.printStackTrace()
135137
AlertDialog.Builder(this)
136-
.setTitle("エラー")
137-
.setMessage("スキンの読み込みに失敗しました: ${e.message}")
138+
.setMessage("スキンの読み込み失敗: ${e.message}")
138139
.setPositiveButton("OK", null)
139140
.show()
140141
}
@@ -150,43 +151,38 @@ class MainActivity : Activity() {
150151
)
151152
}
152153

153-
/** アップロード */
154+
/** 実行ボタン */
154155
private fun handleUpload() {
155-
val bmp = currentSkinBitmap ?: run {
156-
Toast.makeText(this, "スキンが選択されていません", Toast.LENGTH_SHORT).show()
157-
return
158-
}
159-
156+
val bmp = currentSkinBitmap ?: return
160157
val prefs = getSharedPreferences("prefs", MODE_PRIVATE)
161-
val mcToken = prefs.getString("minecraft_token", null) ?: return
162-
val modelType = if (switchModel.isChecked) "slim" else "classic"
158+
val token = prefs.getString("minecraft_token", null) ?: return
159+
val model = if (switchModel.isChecked) "slim" else "classic"
163160

164161
progressBar.visibility = View.VISIBLE
165162
progressBar.progress = 0
166163

167164
scope.launch {
168-
val ok = uploadSkin(mcToken, bmp, modelType) { progress ->
169-
progressBar.progress = progress
170-
}
171-
165+
val ok = uploadSkin(token, bmp, model) { progressBar.progress = it }
172166
progressBar.visibility = View.GONE
167+
173168
Toast.makeText(
174169
this@MainActivity,
175-
if (ok) "アップロード完了" else "アップロード失敗",
176-
Toast.LENGTH_SHORT
170+
if (ok) "アップロード成功" else "アップロード失敗(ログ確認)",
171+
Toast.LENGTH_LONG
177172
).show()
178173
}
179174
}
180175

181-
/** Mojang API 正式対応のスキンアップロード */
176+
/** 本物の Mojang API 仕様に合わせた multipart */
182177
private suspend fun uploadSkin(
183178
token: String,
184179
bmp: Bitmap,
185180
model: String,
186181
onProgress: (Int) -> Unit
187182
): Boolean = withContext(Dispatchers.IO) {
183+
188184
try {
189-
val boundary = "----RabimiSkinBoundary"
185+
val boundary = "----RabimiBoundary"
190186
val url = URL("https://api.minecraftservices.com/minecraft/profile/skins")
191187
val conn = url.openConnection() as HttpURLConnection
192188

@@ -199,47 +195,58 @@ class MainActivity : Activity() {
199195

200196
val out = DataOutputStream(conn.outputStream)
201197

202-
// skinModel
198+
Log.d(TAG, "variant = $model")
199+
200+
// ★ variant が正しいキー名(skinModel ではない)
203201
out.writeBytes("--$boundary\r\n")
204-
out.writeBytes("Content-Disposition: form-data; name=\"skinModel\"\r\n\r\n")
202+
out.writeBytes("Content-Disposition: form-data; name=\"variant\"\r\n\r\n")
205203
out.writeBytes("$model\r\n")
206204

207-
// file
205+
// PNG file
208206
out.writeBytes("--$boundary\r\n")
209207
out.writeBytes("Content-Disposition: form-data; name=\"file\"; filename=\"skin.png\"\r\n")
210208
out.writeBytes("Content-Type: image/png\r\n\r\n")
211209

212-
val pngBaos = ByteArrayOutputStream()
213-
bmp.compress(Bitmap.CompressFormat.PNG, 100, pngBaos)
214-
val bytes = pngBaos.toByteArray()
215-
216-
val chunk = (bytes.size / 100).coerceAtLeast(1)
210+
val png = ByteArrayOutputStream().apply {
211+
bmp.compress(Bitmap.CompressFormat.PNG, 100, this)
212+
}.toByteArray()
217213

214+
val chunk = (png.size / 100).coerceAtLeast(1)
218215
var written = 0
216+
219217
for (i in 0 until 100) {
220218
val start = i * chunk
221-
if (start >= bytes.size) break
222-
val end = ((i + 1) * chunk).coerceAtMost(bytes.size)
223-
out.write(bytes, start, end - start)
219+
if (start >= png.size) break
220+
val end = ((i + 1) * chunk).coerceAtMost(png.size)
221+
out.write(png, start, end - start)
224222
written = end
225223
onProgress(i + 1)
226224
}
227225

228-
// 残り書き込み
229-
if (written < bytes.size) {
230-
out.write(bytes, written, bytes.size - written)
226+
if (written < png.size) {
227+
out.write(png, written, png.size - written)
231228
onProgress(100)
232229
}
233230

234231
out.writeBytes("\r\n--$boundary--\r\n")
235232
out.flush()
236233
out.close()
237234

238-
val rc = conn.responseCode
239-
rc in 200..299
235+
val code = conn.responseCode
236+
Log.d(TAG, "HTTP code = $code")
237+
238+
if (code !in 200..299) {
239+
val err = conn.errorStream?.bufferedReader()?.readText()
240+
Log.e(TAG, "Error response: $err")
241+
} else {
242+
val ok = conn.inputStream.bufferedReader().readText()
243+
Log.d(TAG, "Success: $ok")
244+
}
245+
246+
code in 200..299
240247

241248
} catch (e: Exception) {
242-
e.printStackTrace()
249+
Log.e(TAG, "UPLOAD ERROR", e)
243250
false
244251
}
245252
}

0 commit comments

Comments
 (0)