# 剪刀石頭布遊戲 app 參考 ```kotlin= package tw.josephku.rpsnow import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentWidth import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Button import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import tw.josephku.rpsnow.ui.theme.RPSNowTheme enum class Choice { ROCK, PAPER, SCISSORS } class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { RPSNowTheme { // A surface container using the 'background' color from the theme Surface( modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background ) { RPSNow() } } } } } @Composable fun choiceButton(bvlaue: String, onClick: () -> Unit) { // buttons generator Button( modifier = Modifier .height(130.dp) .width(130.dp) .padding(5.dp), onClick = onClick, shape = RoundedCornerShape(14.dp) ) { Text(text = bvlaue) } } @Composable fun displayChoice(player: String, action: String) { //player and android choices display Text( text = player, fontSize = 16.sp, modifier = Modifier .fillMaxWidth() .wrapContentWidth(Alignment.CenterHorizontally) ) Text( text = action, fontSize = 32.sp, modifier = Modifier .fillMaxWidth() .wrapContentWidth(Alignment.CenterHorizontally), fontWeight = FontWeight.Bold ) } @Composable fun RPSNow() { //main compose val image = painterResource(id = R.drawable.rpsnow_banner) var playerChoiceName by remember { mutableStateOf("--") } var computerChoiceName by remember { mutableStateOf("--") } var playerWins by remember { mutableIntStateOf(0) } var computerWins by remember { mutableIntStateOf(0) } var records by remember { mutableStateOf("0 / 0") } Column { //main column Image( painter = image, contentDescription = null ) Text( text = "Records", fontSize = 30.sp, modifier = Modifier .fillMaxWidth() .wrapContentWidth(Alignment.CenterHorizontally) .padding(top = 16.dp) ) Text( text = records, fontSize = 50.sp, modifier = Modifier .fillMaxWidth() .wrapContentWidth(Alignment.CenterHorizontally), fontWeight = FontWeight.Bold ) Row(modifier = Modifier.padding(top = 85.dp)) { Column( Modifier .fillMaxWidth(0.5f) .wrapContentWidth(Alignment.CenterHorizontally) ) { displayChoice("Your Choice", playerChoiceName) } Column( Modifier .fillMaxWidth() .wrapContentWidth(Alignment.CenterHorizontally) ) { displayChoice("Computer's Choice", computerChoiceName) } } Row(modifier = Modifier.padding(top = 70.dp)) { Choice.entries.forEach { choice -> choiceButton(bvlaue = choice.name) { playerChoiceName = choice.name val computerChoice = Choice.entries.random() computerChoiceName = computerChoice.name val result = (choice.ordinal - computerChoice.ordinal + 3) % 3 when (result) { 0 -> {} 1 -> { playerWins++ } else -> { computerWins++ } } records = "$playerWins / $computerWins" } } } } } @Preview(showBackground = true) @Composable fun DefaultPreview() { RPSNowTheme { RPSNow() } } ``` [Banner 圖](https://slack-files.com/T06ARGM2N-F070MND4L4F-c7943aebdc) **Apktool** https://apktool.org macOS 安裝 ``` $ brew install apktool ``` Windows 安裝 ``` $ choco install apktool ``` Usage: ``` $ apktool d -f app-debug.apk ``` Revise strings.xml ``` $ apktool b app-debug -o new.apk ``` ``` $ keytool -genkey -v -keystore my-test-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias my-alias ``` ``` $ keytool -genkey -v -keystore my-test-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias my-alias ``` ``` $ zipalign -v -p 4 new.apk new-align.apk ``` ``` $ apksigner sign --ks my-test-key.jks --ks-pass pass:12345678 -out new-final.apk new-align.apk ``` zipalign 與 apksigner 在 $ANDROID_HOME/build-tool 中 **ApkLeaks** https://github.com/dwisiswant0/apkleaks macOS 安裝 ``` $ brew install apkleaks ``` PyPi 安裝 ``` $ pip3 install apkleaks ``` Usage: ``` $ apkleaks -f app-debug.apk ```