I forgot to add the permission in the manifest.
Solved
Original Question
I'm developing a little app which allows UX testers to get informations from user's input in android.
For this, I need to create a transparent view in top of all others.
I try to get the permission this way :
class MainActivity : AppCompatActivity() {
val REQUEST_CODE = 10101
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (checkDrawOverlayPermission()) {
//startService(Intent(this, TrackService::class.java))
}
}
fun checkDrawOverlayPermission(): Boolean {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return true
}
if (!Settings.canDrawOverlays(this)) {
val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + packageName))
startActivityForResult(intent, REQUEST_CODE)
return false
} else {
return true
}
}
#TargetApi(Build.VERSION_CODES.M)
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
if (requestCode == REQUEST_CODE) {
if (Settings.canDrawOverlays(this)) {
//startService(Intent(this, TrackService::class.java))
}
}
}
}
But, when I go to the windows (programmatically with this code), I can't grant the access.
Do someone got this problem, or as a fix?
Related
I am trying to make a phone call from the dialog fragment which is inside another fragment. However, my onRequestPermissionsResult() is not being called, whenever I choose allow or deny, it doesn't react. Here is my code:
private val PHONE_REQUEST_CODE = 100;
private lateinit var phonePermission: Array<String>
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
btnOk.setOnClickListener(this)
btnCancel.setOnClickListener(this)
dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
phonePermission = arrayOf(android.Manifest.permission.CALL_PHONE)
}
override fun onClick(v: View?) {
when (v?.id) {
R.id.btnOk -> {
dismiss()
makePhoneCall()
}
R.id.btnCancel -> {
dismiss()
}
}
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
if (requestCode == PHONE_REQUEST_CODE) {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
val intent = Intent(Intent.ACTION_CALL, Uri.parse("tel:" + "111 111 111"))
startActivity(intent)
}
}
}
private fun makePhoneCall(){
if (ContextCompat.checkSelfPermission(
requireContext(),
android.Manifest.permission.CALL_PHONE
) != PackageManager.PERMISSION_GRANTED
) {
requestPermissions(
phonePermission,
PHONE_REQUEST_CODE
)
} else {
val intent = Intent(Intent.ACTION_CALL, Uri.parse("tel:" + "111 111 111"))
startActivity(intent)
}
}
}
I have tried several solutions offered in stackoverflow for similar problems, such as replacing ActivityCompat.requestPermissions() with just requestPermissions(). But still it didn't work.
Thanks in advance
Fragment's "onRequestPermissionsResult" will be called if your hosting activity passed the onRequestPermissionsResult call to base activity.
On fragment parent activity's onRequestPermissionsResult make sure to call super.onRequestPermissionsResult
I’m using Kotlin and trying to return a number from two Activities.
So from MainActivity I get a click (Searchbutton), this starts up my second activity: SearchActivity. When a click happens it then (should!) returns the number 59 to the MainActivity, which I should be able to see in Log.d.
What I actually see is I get the default value “0” being returned to MainActivity?
I’m assuming that the default value indicates that the value hasn’t been passed through the two activities?
Any help really appreciated!
MainActivity.java
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Searchbutton.setOnClickListener {
val intent = Intent(this, SearchActivity::class.java)
startActivity(intent)
var gotthisInt = intent.getIntExtra("MY_KEY", 1);
Log.d("TAG", "What was received= " + gotthisInt)
}
}
}
SearchActivity.java
class SearchActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.fragment_container)
Searchbutton2.setOnClickListener {
val intent = Intent(this#SearchActivity, MainActivity::class.java).apply {
putExtra("MY_KEY", 59)
}
startActivity(intent)
}
}
}
In Android to pass data between Activity, you should use startActivityForResult(Intent, int). So change your code to.
MainActivity.java
class MainActivity : AppCompatActivity() {
private val SEARCH_ACTIVITY_REQUEST_CODE = 1
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Searchbutton.setOnClickListener {
val intent = Intent(this, SearchActivity::class.java)
startActivityForResult(intent, SEARCH_ACTIVITY_REQUEST_CODE)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == SEARCH_ACTIVITY_REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
val gotthisInt = data?.getIntExtra("MY_KEY", 1) ?: 1
Log.d("TAG", "What was received = $gotthisInt")
}
}
}
}
SearchActivity.java
class SearchActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.fragment_container)
Searchbutton2.setOnClickListener {
val data = Intent().apply { putExtra("MY_KEY", 59) }
setResult(Activity.RESULT_OK, data)
finish()
}
}
}
I implemented the Android SMS Verification API on activities and fragments on the same project and it went well. My problem is with fragments in tabs. No matter what I do, onActivityResult always returns result code 0 when "Allow" is pressed. Here's my lot of code which was also implemented and tested to be working on the activities and fragments.
override fun onStart() {
super.onStart()
registerToSmsBroadcastReceiver()
}
override fun onStop() {
myActivity.unregisterReceiver(smsBroadcastReceiver)
super.onStop()
}
private fun startSmsUserConsent() {
SmsRetriever.getClient(myActivity).also {
it.startSmsUserConsent(null)
.addOnSuccessListener {
Log.d("LISTENING", "SUCCESS")
}
.addOnFailureListener {
Log.d("LISTENING", "FAIL")
}
}
}
private fun registerToSmsBroadcastReceiver() {
smsBroadcastReceiver = SmsBroadcastReceiver().also {
it.smsBroadcastReceiverListener =
object : SmsBroadcastReceiver.SmsBroadcastReceiverListener {
override fun onSuccess(intent: Intent?) {
intent?.let { context -> startActivityForResult(context, REQ_USER_CONSENT) }
}
override fun onFailure() {
}
}
}
val intentFilter = IntentFilter(SmsRetriever.SMS_RETRIEVED_ACTION)
myActivity.registerReceiver(smsBroadcastReceiver, intentFilter)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
REQ_USER_CONSENT -> {
if ((resultCode == Activity.RESULT_OK) && (data != null)) {
val message = data.getStringExtra(SmsRetriever.EXTRA_SMS_MESSAGE)
val code = message?.let { fetchVerificationCode(it) }
otpField.setText(code)
}
}
}
}
private fun fetchVerificationCode(message: String): String {
return Regex("(\\d{6})").find(message)?.value ?: ""
}
Oh, and startSmsUserConsent() is called whenever I call for the API to send an OTP. Anything I missed?
Thank you.
I solved the issue by handling the OTP SMS Retrieval on the activity instead of on the fragment, then passed on the fragment if need be.
In my Android application, when I pick a contact from the Contacts activity, instead of returning to the activity that called it, the application closes without any exception or error message.
I tried to launch this activity with different flags, but with no result
class AddPhoneCompatActivity : BaseCompatActivity(), AddPhoneContract.View, View.OnClickListener {
#Inject
lateinit var presenter: AddPhonePresenter
override fun init(savedInstanceState: Bundle?) {
log("Add phone screen - Loading view", LOGS_SIMPLE_FILE_NAME)
setContentView(R.layout.activity_add_phone)
MyLocationNotifierApp.getInjector().inject(this)
presenter.attach(this)
GeneralUtil.checkPermission(
Manifest.permission.READ_CONTACTS,
GeneralUtil.READ_CONTACTS_REQUEST_CODE,
applicationContext,
this
)
presenter.checkIntent(intent)
btnAddPhoneFromContacts.setOnClickListener(this)
btnPhoneNext.setOnClickListener(this)
}
override fun onBackPressed() {
goBack()
}
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
when(item?.itemId) {
android.R.id.home -> {
goBack()
}
}
return true
}
private fun goBack() {
intent.setClass(this, AddLabelCompatActivity::class.java)
intent.putExtra(GeneralUtil.PHONE_SERIALIZATION_KEY, edAddPhoneNum.text.toString())
startActivity(intent)
finish()
}
override fun onClick(v: View?) {
when (v?.id) {
btnAddPhoneFromContacts.id -> {
log("Starting contacts picker", LOGS_SIMPLE_FILE_NAME)
val intent = Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI)
intent.type = ContactsContract.CommonDataKinds.Phone.CONTENT_TYPE;
startActivityForResult(intent, GeneralUtil.REQUEST_CODE_SEARCH_CONTACT)
}
btnPhoneNext.id -> {
presenter.proceedNext(edAddPhoneNum.text.toString(), intent)
}
}
}
override fun updatePhoneEditField(phoneNum: String?) = edAddPhoneNum.setText(phoneNum)
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
log("Add phone screen - onActivityResult called. Checking passed data.", LOGS_SIMPLE_FILE_NAME)
if (requestCode == GeneralUtil.REQUEST_CODE_SEARCH_CONTACT) {
if (resultCode == Activity.RESULT_OK) {
presenter.processAddPhoneRequestFomIntent(data)
}
}
}
}
It is supposed that after picking a contact, I return to the activity and show a dialog with the list of phone numbers corresponding to the contact. But instead, the the app closes without any notification.
Found the reason. The entity creation flow is not using startActivityForResult, but the pieces of data passed between activities. And I started this flow in the starting activity using flags Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NO_HISTORY. When I deleted this line in the starting flow activity, it began working as intended.
I am trying to pass a value from Activity 3 to Activity 2 but I am getting null Value. If I click Back button its going to previous Activity but value is null. Added the suggested Approach code below. but still not able to get the results.
Suggested Approach:
Activity :3
override fun onBackPressed() {
sendDataBackToPreviousActivity()
super.onBackPressed()
}
private fun sendDataBackToPreviousActivity()
{
val navBarTitle21=intent.getStringExtra(TestProjectMenuViewHolder.TEST_TITLE_NAME)
val intent=Intent().apply { putExtra("ReturnMessage",navBarTitle21)}
setResult(Activity.RESULT_OK,intent)
}
Activity:2
Main Class:
companion object {
const val START_ACTIVITY_3_REQUEST_CODE = 0
}
val intent=Intent(this,TestProjectMenuDetail::class.java)
startActivityForResult(intent, START_ACTIVITY_3_REQUEST_CODE)
Declared outside Main Class:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == START_ACTIVITY_3_REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
val message = data!!.getStringExtra("ReturnMessage")
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
println("Message Value: $message")
}
} else {
super.onActivityResult(requestCode, resultCode, data)
}
}
First Approach:
Activity:3
val navBarTitle= intent.getStringExtra(TestMenuViewHolder.TEST_TITLE_KEY)
supportActionBar?.title=navBarTitle//Something Like "StackOverFlow". THis is for back Button
TestMenuDetail:
val navBarTitle2=intent.getStringExtra(TestMenuViewHolder.TEST_TITLE_NAME)
val TestVar=Intent(this#TestMenuDetail,TestMenuList::class.java)
intent.putExtra("TestVar2",navBarTitle2)
println("Test Value $navBarTitle2")//Test Value Hello
Activity:2
TestMenuList:
val navBarTitle3=intent.getStringExtra("TestVar2")
println("Helllo Test: $navBarTitle3")//Helllo Test: null
You should use startActivityForResult API to achieve your task.
Activity2.kt
class Activity2 : AppCompatActivity() {
companion object {
const val START_ACTIVITY_3_REQUEST_CODE = 0
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity2)
// Start Activity3
val intent = Intent(this, Activity3::class.java)
startActivityForResult(intent, START_ACTIVITY_3_REQUEST_CODE)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == START_ACTIVITY_3_REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
val message = data!!.getStringExtra("message")
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}
} else {
super.onActivityResult(requestCode, resultCode, data)
}
}
}
Activity3.kt
class Activity3 : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity3)
}
override fun onBackPressed() {
sendDataBackToPreviousActivity()
super.onBackPressed()
}
/**
* Send data back to previous activity which start this one, you can call this method when users press on back key
* or when users press on a view (button, image, etc) on this activity.
*/
private fun sendDataBackToPreviousActivity() {
val intent = Intent().apply {
putExtra("message", "This is a message from Activity3")
// Put your data here if you want.
}
setResult(Activity.RESULT_OK, intent)
}
}
Ok here is what I would do:
Override the onBackPressed method and then pass the variable value inside the method with an Intent. And in activity 2 receive the value from activity 3.
In activity 3
#override
public void onBackPressed (){
Intent intent = new Intent(getApplicationContext(), Activity2.class);
intent.put("value_key", value);
startActivity(intent);
}
Receive value in activity 2
getIntent.getValue("value_key");
Don't forget to check the syntax, I just wrote it from my phone. Hope it helps!
You can always use SharedPreferences, and then clear them, after receiving data in previous activity. It's 100% effective way. Put it:
val sharedPreference = getSharedPreferences("prefs name",Context.MODE_PRIVATE)
var editor = sharedPreference.edit()
editor.putString("your value name","value")
editor.commit()
and get it:
sharedPreference.getString("your value name","default value")
but of course you have to open preferences again in previous activity ;)
val sharedPreference = getSharedPreferences("prefs name",Context.MODE_PRIVATE)