package com.manhvan.safekidchild import android.app.Activity import android.os.Bundle import android.content.Intent import android.net.Uri import android.provider.OpenableColumns import android.view.ViewGroup import android.widget.* import java.io.* import java.net.HttpURLConnection import java.net.URL import java.util.UUID class MainActivity : Activity() { private val pickCode = 9001 private val prefs by lazy { getSharedPreferences("safekid", MODE_PRIVATE) } private lateinit var server: EditText private lateinit var token: EditText private lateinit var status: TextView override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val box=LinearLayout(this).apply { orientation=LinearLayout.VERTICAL; setPadding(32,48,32,32) } fun label(t:String)=TextView(this).apply{ text=t; textSize=14f } box.addView(TextView(this).apply{ text="SafeKid Child"; textSize=28f }) box.addView(label("API Server")) server=EditText(this).apply{ setText(prefs.getString("server","https://YOUR-DOMAIN/backend/public")!!); hint="https://.../backend/public" } box.addView(server, LinearLayout.LayoutParams(-1,-2)) box.addView(label("Device Token")) token=EditText(this).apply{ setText(prefs.getString("token","")!!); hint="Device Token" } box.addView(token, LinearLayout.LayoutParams(-1,-2)) val pick=Button(this).apply{ text="Chọn ảnh / video để đồng bộ"; setOnClickListener{save();pickMedia()} } box.addView(pick) status=TextView(this).apply{ text="Sẵn sàng"; textSize=16f; setPadding(0,24,0,0) } box.addView(status) setContentView(box) } private fun save(){prefs.edit().putString("server",server.text.toString().trim().trimEnd('/')).putString("token",token.text.toString().trim()).apply()} private fun pickMedia(){ val i=Intent(Intent.ACTION_OPEN_DOCUMENT).apply{ type="*/*"; putExtra(Intent.EXTRA_MIME_TYPES,arrayOf("image/*","video/*"));putExtra(Intent.EXTRA_ALLOW_MULTIPLE,true);addCategory(Intent.CATEGORY_OPENABLE) };startActivityForResult(i,pickCode) } override fun onActivityResult(req:Int,result:Int,data:Intent?){super.onActivityResult(req,result,data);if(req!=pickCode||result!=RESULT_OK||data==null)return;val uris=mutableListOf();data.clipData?.let{for(i in 0 until it.itemCount)uris.add(it.getItemAt(i).uri)} ?: data.data?.let{uris.add(it)};status.text="Đang đồng bộ ${uris.size} file...";Thread{var ok=0;for(u in uris){try{upload(u);ok++;runOnUiThread{status.text="Đã đồng bộ $ok/${uris.size}"}}catch(e:Exception){runOnUiThread{status.text="Lỗi: ${e.message}"}}}}.start()} private fun upload(uri:Uri){ val cr=contentResolver;val name=cr.query(uri,null,null,null,null)?.use{c->val n=c.getColumnIndex(OpenableColumns.DISPLAY_NAME);if(c.moveToFirst()&&n>=0)c.getString(n) else "media"} ?: "media";val size=cr.query(uri,null,null,null,null)?.use{c->val n=c.getColumnIndex(OpenableColumns.SIZE);if(c.moveToFirst()&&n>=0)c.getLong(n) else -1} ?: -1;val conn=URL(server.text.toString().trimEnd('/')+"/api/media/upload").openConnection() as HttpURLConnection;val boundary="----SafeKid${UUID.randomUUID()}";conn.requestMethod="POST";conn.doOutput=true;conn.setRequestProperty("X-Device-Token",token.text.toString().trim());conn.setRequestProperty("Content-Type","multipart/form-data; boundary=$boundary");val out=DataOutputStream(BufferedOutputStream(conn.outputStream));fun field(k:String,v:String){out.writeBytes("--$boundary\r\nContent-Disposition: form-data; name=\"$k\"\r\n\r\n$v\r\n")};field("client_id",UUID.nameUUIDFromBytes((uri.toString()+size).toByteArray()).toString());field("file_name",name);out.writeBytes("--$boundary\r\nContent-Disposition: form-data; name=\"file\"; filename=\"${name.replace("\"","_")}\"\r\nContent-Type: ${cr.getType(uri)?:"application/octet-stream"}\r\n\r\n");cr.openInputStream(uri).use{input->val buf=ByteArray(64*1024);while(true){val n=input?.read(buf)?:-1;if(n<0)break;out.write(buf,0,n)}};out.writeBytes("\r\n--$boundary--\r\n");out.flush();out.close();val code=conn.responseCode;if(code !in 200..299){val err=conn.errorStream?.bufferedReader()?.readText();throw IOException("HTTP $code ${err?:(conn.responseMessage?:"")}")};conn.disconnect() } }