first commit

This commit is contained in:
nuryuda 2025-11-20 20:58:29 +07:00
parent 9d34345d24
commit f4c6069f21
4 changed files with 220 additions and 32 deletions

View File

@ -22,6 +22,12 @@
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity
android:name=".JalurEvakuasiActivity"
android:exported="false"/>
</application> </application>
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
</manifest> </manifest>

View File

@ -0,0 +1,47 @@
package id.ac.ubharajaya.panicbutton
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.*
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
class JalurEvakuasiActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
JalurEvakuasiScreen(onClose = { finish() })
}
}
}
@Composable
fun JalurEvakuasiScreen(onClose: () -> Unit) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Image(
painter = painterResource(id = R.drawable.evakuasiselatan),
contentDescription = "Jalur Evakuasi",
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(20.dp))
Button(onClick = onClose) {
Text("Close")
}
}
}

View File

@ -1,15 +1,25 @@
package id.ac.ubharajaya.panicbutton package id.ac.ubharajaya.panicbutton
import android.content.Intent
import android.os.Bundle import android.os.Bundle
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.material3.Button import androidx.compose.foundation.text.BasicTextField
import androidx.compose.material3.Text import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.*
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import okhttp3.MediaType.Companion.toMediaType import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
@ -19,64 +29,189 @@ class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContent { setContent {
MyApp() MyApp(
onClose = { finish() },
onOpenEvacuation = {
startActivity(Intent(this, JalurEvakuasiActivity::class.java))
}
)
} }
} }
} }
// Emoji untuk tiap kondisi
fun getEmoji(condition: String): String {
return when (condition) {
"Kebakaran" -> "🐦‍🔥"
"Banjir" -> "😒"
"Tsunami" -> "🐳"
"Gunung Meletus" -> "🤯"
"Gempa Bumi" -> "😫"
"Huru Hara/Demonstrasi" -> "😮"
"Binatang Buas" -> "💀"
"Radiasi Nuklir" -> "😶‍🌫️"
"Biohazard" -> "🥶"
else -> ""
}
}
@Composable @Composable
fun MyApp() { fun MyApp(onClose: () -> Unit, onOpenEvacuation: () -> Unit) {
// State untuk menampilkan hasil request val focusManager = LocalFocusManager.current
var message by remember { mutableStateOf("Klik tombol untuk mengirim notifikasi") } var message by remember { mutableStateOf("Klik tombol untuk mengirim notifikasi") }
var selectedConditions by remember { mutableStateOf(mutableSetOf<String>()) }
var additionalNotes by remember { mutableStateOf(TextFieldValue("")) }
// UI
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.padding(16.dp), .padding(16.dp),
verticalArrangement = Arrangement.Center, verticalArrangement = Arrangement.Top,
horizontalAlignment = Alignment.CenterHorizontally horizontalAlignment = Alignment.Start
) { ) {
Text(text = message, Modifier.padding(bottom = 16.dp)) // Judul
Button(onClick = { Text(
// Kirim HTTP request saat tombol ditekan text = "Terjadi Kondisi Darurat:",
sendNotification { response -> fontSize = 26.sp,
message = response fontWeight = FontWeight.Bold,
color = Color.Red,
modifier = Modifier.padding(bottom = 16.dp)
)
// Daftar kondisi
listOf(
"Kebakaran",
"Banjir",
"Tsunami",
"Gunung Meletus",
"Gempa Bumi",
"Huru Hara/Demonstrasi",
"Binatang Buas",
"Radiasi Nuklir",
"Biohazard",
"Lainnya"
).forEach { condition ->
val emoji = getEmoji(condition)
Row(
modifier = Modifier
.fillMaxWidth()
.clickable {
focusManager.clearFocus()
selectedConditions = selectedConditions.toMutableSet().apply {
if (contains(condition)) remove(condition) else add(condition)
}
}
.padding(vertical = 4.dp),
verticalAlignment = Alignment.CenterVertically
) {
Checkbox(
checked = selectedConditions.contains(condition),
onCheckedChange = { isChecked ->
focusManager.clearFocus()
selectedConditions = selectedConditions.toMutableSet().apply {
if (isChecked) add(condition) else remove(condition)
}
}
)
Text(
text = "$emoji $condition",
modifier = Modifier.padding(start = 8.dp)
)
} }
}) {
Text(text = "Kirim Alert")
} }
// Catatan tambahan
Spacer(modifier = Modifier.height(16.dp))
Text(text = "Catatan tambahan:", fontWeight = FontWeight.Bold)
BasicTextField(
value = additionalNotes,
onValueChange = { additionalNotes = it },
modifier = Modifier
.fillMaxWidth()
.height(100.dp)
.padding(8.dp)
.border(1.dp, Color.Gray),
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done)
)
// ================================================
// Tombol Kirim + Lihat Jalur Evakuasi (Berdampingan)
// ================================================
Spacer(modifier = Modifier.height(16.dp))
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
// Tombol Kirim Laporan
Button(
onClick = {
val notes = additionalNotes.text
val conditions = selectedConditions.joinToString(", ") {
"${getEmoji(it)} $it"
}
val report = "Kondisi: $conditions\nCatatan: $notes"
sendNotification(report) { response ->
message = response
}
},
modifier = Modifier.weight(1f),
colors = ButtonDefaults.buttonColors(containerColor = Color.Black)
) {
Text(text = "Kirim Laporan", color = Color.Yellow)
}
Spacer(modifier = Modifier.width(12.dp))
// Tombol Jalur Evakuasi
Button(
onClick = onOpenEvacuation,
modifier = Modifier.weight(1f),
colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF0080FF))
) {
Text(text = "Lihat Jalur Evakuasi", color = Color.White)
}
}
Spacer(modifier = Modifier.height(16.dp))
Text(
text = "“JANGAN PANIK! SEGERA EVAKUASI\nDIRI ANDA KE TITIK KUMPUL”",
color = Color.Red,
fontSize = 15.sp
)
Spacer(modifier = Modifier.height(20.dp))
// Tombol Tutup (opsional)
Button(onClick = onClose) {
Text("Tutup")
}
Spacer(modifier = Modifier.height(16.dp))
Text(text = message)
} }
} }
// ===============================================================
// Fungsi untuk mengirimkan HTTP request // Fungsi Kirim Notifikasi ke Server ntfy.ubharajaya.ac.id
fun sendNotification(onResult: (String) -> Unit) { // ===============================================================
fun sendNotification(report: String, onResult: (String) -> Unit) {
val client = OkHttpClient() val client = OkHttpClient()
val url = "https://ntfy.ubharajaya.ac.id/panic-button" // Ganti <your-topic> dengan topik Anda val url = "https://ntfy.ubharajaya.ac.id/panic-button"
val requestBody = RequestBody.create(
"text/plain".toMediaType(), // Mengirim plain text
"Notifikasi dari Satrio Putra Wardani 202310715307" // Pesan yang akan tampil
)
val requestBody = RequestBody.create("text/plain".toMediaType(), report)
val request = Request.Builder() val request = Request.Builder()
.url(url) .url(url)
.addHeader("Title", "Alert") .addHeader("Title", "Alert")
.addHeader("Priority", "urgent") .addHeader("Priority", "urgent")
.addHeader("Tags", "alert warning,rotating_light")
.post(requestBody) .post(requestBody)
.build() .build()
// Eksekusi request di thread terpisah
Thread { Thread {
try { try {
val response = client.newCall(request).execute() val response = client.newCall(request).execute()

Binary file not shown.

After

Width:  |  Height:  |  Size: 524 KiB