I'm using the relatively new Adobe Air run-time permissions for Android, to make use of the file system.
The problem is that when the user refuses to give permission which is essential, I would like to ask him again, yet the event handler is not being called upon rejection.
file.addEventListener(PermissionEvent.PERMISSION_STATUS, function(e:PermissionEvent):void {
// does not reach to this point if user declined permission request
if (e.status == PermissionStatus.GRANTED)
{
contRead();
}});
try {
file.requestPermission();
} catch(e:Error)
{
// another request is in progress
trace("REQUEST ERROR!!!");
}
How do I tackle it? Do you have a separate event handler?
I'm using Adobe Air 25.
Thanks.
You need to create a separate function, so it can be called multiple times whenever it's needed. Right now, in your code, it only exists once (when the evenListener is added).
Try something like this setup below :
file.addEventListener(PermissionEvent.PERMISSION_STATUS, checkPermissions);
try
{ file.requestPermission(); }
catch(e:Error)
{
// another request is in progress
trace( "REQUEST ERROR!!! : " + e.toString() );
}
function checkPermissions (e:PermissionEvent) : void
{
trace( "Status is : " + e.status.toString() );
// does not reach to this point if user declined permission request
if (e.status == PermissionStatus.GRANTED)
{ contRead(); }
}
Related
I've spend a day on this issue, and I'm stumped. I've read through numerous similar questions, and tried all the suggestions, but nothing worked for me.
I have an app, with a preference screen where the user can turn on Bluetooth. The preference screen sends an intent to the MainActivity, which then checks security permissions and if needed requests permission.
I am building against version SDK version 32.
In Manifest I have:
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-feature android:name="android.hardware.bluetooth" android:required="true"/>
In MainActivity I check if permission is already granted:
private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (Objects.equals(intent.getAction(), CustomIntent.CHECK_BLUETOOTH_SECURITY_PERMISSION)) {
int check = ContextCompat.checkSelfPermission( thisActivity, Manifest.permission.BLUETOOTH_CONNECT );
if ( check == PackageManager.PERMISSION_DENIED )
getPermission( Manifest.permission.BLUETOOTH_CONNECT, RequestCodes.BT_SECURITY_REQUEST.ordinal() );
}
and if not, I request permission.
When requesting permission, I have tried the old way with:
public void getPermission( String permission, int requestCode ) {
if ( shouldShowRequestPermissionRationale( permission ) ) {
// TODO: display a dialog to explain the reason for needing the permission
Toast.makeText( this, "Need to put together an explanation for the permission", Toast.LENGTH_LONG ).show();
} else {
requestPermissions( new String[]{ permission }, requestCode );
}
}
I have tried both with CompactActivity.requestPermissions and with just requestPermissions as above.
and I have also tried with the new way. In onCreate I have:
activityResultLauncher = registerForActivityResult(
new ActivityResultContracts.RequestMultiplePermissions(), new ActivityResultCallback<Map<String, Boolean>>() {
#Override
public void onActivityResult(Map<String, Boolean> result) {
Log.e("ActivityResultLauncher", ""+result.toString() );
Boolean areAllGranted = true;
for ( Boolean b : result.values() ) {
areAllGranted = areAllGranted && b;
}
if ( areAllGranted )
Log.e( "ActivityResultLauncher","It worked");
else
Log.e( "ActivityResultLauncher", "wah wah wah");
}
});
and in getPermission() i then call
activityResultLauncher.launch(new String[]{
Manifest.permission.BLUETOOTH_CONNECT
});
But no matter what I do, the user dialog asking the user to grant permission never show, and the onPermissionRequestResult just immediately return with False, i.e. Denied.
I don't see any error messages in the LogCat (outside of the log entries I put there myself). I've also tried to step through the Android libraries to see i can see any exception thrown, but all looks fine there as well.
UPDATE
Just as I posted this, I tried to clear the emulator device.
After that, the first time I ran the code, the app crashed, hard.
I was able to catch this in logCat
Attempting to launch an unregistered ActivityResultLauncher with >contract
androidx.activity.result.contract.ActivityResultContracts$RequestMultiplePermissions
and input [Ljava.lang.String. You must ensure the
ActivityResultLauncher is registered before calling launch().
I do register the activityResultLauncher in onCreate. So I'm not clear on why it doesn't know it's registered.
It's also weird that this error only happens first time I run the app after clearing device files.
Then I launched the app again, (without changing anything in my code) and this time it worked. The dialog was displayed, and I could grant permissions.
Anyone know what in the world is going on?
I once wrote a quick ‘offline.html‘. Just be be sure I understood how offline PWA worked:
This is offline.html (My App Name)
I thought it worked as expected. So I deleted it and wrote a better one, with a back button, some info etc.
Now when this app is offline it starts on the page the manifest.json days, as expected.
However, if I try to refresh the page that spooky "offline.html" shows up. From nowhere.
I've tried to understand where it lurks, but I can't find it. (The new "offline.htmi" is there when I go to it in the web browser.)
I've tried Firefox offline on my mobile to see if the spoky "offline.html" jumps up there to. It does. 😐
I've cleared the cache in Chrome. The spoky "offline.html" is still there.
Any ideas?
(This is on Android 9)
Offline pages are not exactly stored in caches as regular cached items, there are stored quite differently, relative to the current installed service worker. I tried looking for an article to explain this more but can't walk around any currently.
However you'll have to unregister your service worker or learn how Updating service worker works,
The aim is to remove the lurking offline.html served to the new offline.html that exists.
This is what I finally landed on. It seems to work. The test for 404 is of course not optimal, but I leave it that way for now, hoping that the emerging standard will address this issue soon.
async function setupServiceWorker() {
let reg;
if (navigator.serviceWorker.controller) {
console.log("Active service worker found, no need to register");
// new Popup("registered service worker, .active.scriptURL", reg.active.scriptURL, null, true).show();
reg = await navigator.serviceWorker.getRegistration();
} else {
reg = await navigator.serviceWorker.register("service-worker.js", { scope: "./" });
console.log("Service-worker.js registered, scope: " + reg.scope);
}
try {
if (navigator.onLine) {
const newReg = await reg.update();
}
} catch (err) {
const is404 = err.message.match("404");
new Popup("err", is404 + " " + err.message).show();
if (is404) {
let wasUnregistered;
try {
wasUnregistered = await reg.unregister();
} catch (errUnreg) {
new Popup("unregister() service worker failed", errUnreg.message).show();
}
if (wasUnregistered) {
setTimeout(setupServiceWorker, 1000);
}
}
}
}
setTimeout(setupServiceWorker, 5000);
I have a networkStateReceiver, that checks if I have internet or not.
If I do, I reinitiate instabug, if not, I want to deactivate. How can I do that?
I tried just setting it as null, but it doesn't work.
if(haveConnectedMobile || haveConnectedWifi){
//TODO will need to make a queue, and go through all that queue
PSLocationCenter.getInstance().initInstabug();
}else{
PSLocationCenter.getInstance().instabug = null;
}
This is my init:
public void initInstabug() {
String[] feedbackArray = getResources().getStringArray(R.array.feedback);
String randomStr = feedbackArray[new Random().nextInt(feedbackArray.length)];
Instabug.DEBUG = true;
instabug = Instabug.initialize(this)
.setAnnotationActivityClass(InstabugAnnotationActivity.class)
.setShowIntroDialog(true, PSTimelineActivity.class)
.enableEmailField(true, false)
.setEnableOverflowMenuItem(true)
.setDebugEnabled(true)
.setCommentRequired(true)
.setPostFeedbackMessage(randomStr)
.setPostBugReportMessage(randomStr) //TODO will be the post report message, random from array
.setCommentFieldHint("Please describe what went wrong")
.setPreSendingRunnable(new Runnable() {
#Override
public void run() {
String[] files = new String[2];
files[0] = Environment.getExternalStorageDirectory() + "/Passenger/passenger_log.txt";
files[1] = Environment.getExternalStorageDirectory() + "/Passenger/passenger_log2.txt";
Compress compress = new Compress(files, Environment.getExternalStorageDirectory() + "/Passenger/log.zip");
compress.zip(new CrudStateCallback() {
#Override
public void onResponse(String string) {
Log.i("", "ended making the archive");
}
});
}
})
.attachFileAtLocation(Environment.getExternalStorageDirectory() + "/Passenger/log.zip");
}
You can use this code to disable Instabug automatic invocation:
Instabug.getInstance().setInvocationEvent(IBGInvocationEvent.IBGInvocationEventNone)
This way it won't be invoked automatically. This will only affect the next Activity though (not the current one). You may force to stop and restart all listeners by calling onPause and onResume on the current Activity. (We may address that soon though, so that such changes are applied on the currently running Activity).
Don't forget to also enable the shake invocation event when internet access is restored.
Please keep in mind that Instabug SDK already caches all reports and will re-attempt to send them on next app launch until they're uploaded successfully.
Just wanted to post the updated answer.
The newer SDK has changed the name and now you can disable it by the following code:
Instabug.changeInvocationEvent(InstabugInvocationEvent.NONE)
Notice, if you want to disable it for entire application, just call this method in your Application class
I'm trying to implement Facebook sharing in my game using Unity 3D + Facebook Unity SDK. But when I tried testing to post to my wall, this error shows up: "We are Sorry, this post is no longer available. It may have been removed." Can anybody help me? Thanks in advance.
BTW, here's my code:
using UnityEngine;
using System.Collections;
public class FacebookController : MonoBehaviour {
public bool isUsingFacebook = true; //Are we using Facebook SDK? This variable is only
//Feed parameters.
private string link = "market://details?id=com.LaserCookie.Queue"; //The link that will show the user the game's google play store address
private string linkName = "Queue"; //The link name
private string linkCaption = "Wow this game is great! 10/10 must play!"; // The caption of the link
private string linkDescription = "I achieved the score of " + PlayerController.instance.score.ToString() + "! Try to beat me if you can!"; //The description of the link
private string picture = "http://www.drycreekequestriancenter.com/testImage.jpeg"; //This is the image / game icon for the link. For now, it's shamelessly got from a random source. Thank you, random citizen...
void Awake()
{
}
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
//Init FB
private void Init()
{
if (!FB.IsInitialized)
{
FB.Init(OnInitComplete, OnHideUnity);
}
}
//Callback that will be called when the initialization is completed
private void OnInitComplete()
{
Debug.Log("FB.Init completed: Is user logged in? " + FB.IsLoggedIn);
//Check if we are logged in.
//If not, we will log in.
//If we are, post status.
if (!FB.IsLoggedIn)
{
LoginWithPublish();
}
else
{
PostImpl();
}
}
//Callback that will be called when the game is shown / not
private void OnHideUnity(bool isGameShown)
{
Debug.Log("Is game showing? " + isGameShown);
}
//Post to Facebook. This is the only exposed method because we only use this to post to Facebook.
//The initialization and login will be called when needed.
//It will first detect whether or not we have been initialized. And will init if we haven't.
//Then it will check whether or not we have been logged in with publish. And will log in if not.
public void PostToFacebook()
{
//Are we using facebook SDK?
if (isUsingFacebook)
{
if (!FB.IsInitialized) //Check for initialization
{
Init();
}
else if (!FB.IsLoggedIn) //Check for login
{
LoginWithPublish();
}
else //Post if we are already initia;ized and logged in
{
PostImpl();
}
}
}
//The true implementation of the posting
private void PostImpl()
{
FB.Feed("",link, linkName,linkCaption,linkDescription,picture);
}
//Login to Facebook with publish
private void LoginWithPublish()
{
// It is generally good behavior to split asking for read and publish
// permissions rather than ask for them all at once.
//
// In your own game, consider postponing this call until the moment
// you actually need it.
FB.Login("publish_actions", LoginCallback);
}
//Login callback
void LoginCallback(FBResult result)
{
if (result.Error != null)
{
Debug.Log( "Error Response:\n" + result.Error );
//TODO: Retry login if we have error? Or do we display a pop up?
}
else if (!FB.IsLoggedIn)
{
Debug.Log( "Login cancelled by Player" );
//TODO: Do we display a pop up?
}
else
{
Debug.Log( "Login was successful!" );
PostImpl();
}
}
}
You need to add Key Hash for FB application.
Go to My Apps, select you application, open Setting tab, add platform for android, and add you key hash.
check this link out
Setting a Release Key Hash
I've fixed the issue. It turns out it's because I used my still in development google store address as the link. I thought it would be automatically recognized regardless of my app is live or not. Thank you anyway. :)
I am using titanium sdk for mobile app development.
I was just searching for any way that i can prevent the camera from saving the image. I dont want to save the image till a few steps down the line so that all the information has been verified.
What i mean to say is that suppose after after clicking the image through the app if user selects the cancel button the image should not be present in the gallery.
Functionality is needed both on IOS and android.
Thanks a lot ...
You need to set the saveToPhotoGallery to false and on the success function of the Titanium.Media.showCamera() put your logic and when they click on the save button save to the gallery
Titanium.Media.showCamera({
success:function(event) {
// called when media returned from the camera
Ti.API.debug('Our type was: '+event.mediaType);
if(event.mediaType == Ti.Media.MEDIA_TYPE_PHOTO) {
//
//add your logic here
//
//onSave
Titanium.Media.saveToPhotoGallery(event.media);
} else {
alert("got the wrong type back ="+event.mediaType);
}
},
cancel:function() {
// called when user cancels taking a picture
},
error:function(error) {
// called when there's an error
var a = Titanium.UI.createAlertDialog({title:'Camera'});
if (error.code == Titanium.Media.NO_CAMERA) {
a.setMessage('Please run this test on device');
} else {
a.setMessage('Unexpected error: ' + error.code);
}
a.show();
},
saveToPhotoGallery: false,
allowEditing: true,
mediaTypes: [Ti.Media.MEDIA_TYPE_PHOTO]
});