Compare commits

..

5 Commits

6 changed files with 29 additions and 276 deletions

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetSelector">
<selectionStates>
<SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" />
</SelectionState>
</selectionStates>
</component>
</project>

View File

@ -33,13 +33,4 @@ Repository ini digunakan untuk praktikum perkuliahan pemrograman mobile.
- 22. Hadi Guna Prakoso (202310715312)
- 23. Muhammad Rafi (202310715191)
- 24. Muhammad Rafly Al-Fathir (202310715043)
- 25. Lalu Muhammad Anggana Subhan (202310715277)
# Kelompok 6
- Faris Naufal Priatna (202310715123)
- Nuryuda Maulana (202310715038)
- Satrio Putra Wardani (202310715307)
Latihan Praktikum 1: Mengganti icon menjadi lingkaran merah dengan menambahkan gambar red_button.jpg
Latihan Praktikum 2: Menambahkan emoji pada setiap bencana dan menambahkan gambar denah untuk jalur evakuasi selatan.jpg
- 25. Jeremia Sebastian Marpaung (202310715096)

View File

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

View File

@ -1,47 +0,0 @@
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,25 +1,18 @@
package id.ac.ubharajaya.panicbutton
import android.content.Intent
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
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.sp
import androidx.compose.ui.tooling.preview.Preview
import id.ac.ubharajaya.panicbutton.ui.theme.PanicButtonTheme
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
@ -28,200 +21,32 @@ import okhttp3.RequestBody
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
MyApp(
onClose = { finish() },
onOpenEvacuation = {
startActivity(Intent(this, JalurEvakuasiActivity::class.java))
PanicButtonTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
Greeting(
name = "Android",
modifier = Modifier.padding(innerPadding)
)
}
)
}
}
}
}
// 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
fun MyApp(onClose: () -> Unit, onOpenEvacuation: () -> Unit) {
val focusManager = LocalFocusManager.current
var message by remember { mutableStateOf("Klik tombol untuk mengirim notifikasi") }
var selectedConditions by remember { mutableStateOf(mutableSetOf<String>()) }
var additionalNotes by remember { mutableStateOf(TextFieldValue("")) }
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.Top,
horizontalAlignment = Alignment.Start
) {
// Judul
Text(
text = "Terjadi Kondisi Darurat:",
fontSize = 26.sp,
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)
)
}
}
// 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)
}
fun Greeting(name: String, modifier: Modifier = Modifier) {
Text(
text = "Hello $name!",
modifier = modifier
)
}
// ===============================================================
// Fungsi Kirim Notifikasi ke Server ntfy.ubharajaya.ac.id
// ===============================================================
fun sendNotification(report: String, onResult: (String) -> Unit) {
val client = OkHttpClient()
val url = "https://ntfy.ubharajaya.ac.id/panic-button"
val requestBody = RequestBody.create("text/plain".toMediaType(), report)
val request = Request.Builder()
.url(url)
.addHeader("Title", "Alert")
.addHeader("Priority", "urgent")
.post(requestBody)
.build()
Thread {
try {
val response = client.newCall(request).execute()
if (response.isSuccessful) {
onResult("Notifikasi berhasil dikirim!")
} else {
onResult("Gagal mengirim notifikasi: ${response.code}")
}
} catch (e: Exception) {
onResult("Error: ${e.message}")
}
}.start()
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
PanicButtonTheme {
Greeting("Android")
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 524 KiB