Android Question Help: FLAG_IMMUTABLE or FLAG_MUTABLE

Zeev Goldstein

Well-Known Member
Licensed User
Longtime User
hi,

i get this error message when running on phone with android 13
on version 9 it works
i set targetsdk to 31
when reduce it to 30 it works on the new phone

my B4A version is 12

searching the forum i found some other posts on that topic and they were referred to use NB6 - here i got lost
i couldn't find any sample that works as all are either partial or used for services which i don't

i don't want to use sdk less than 31 as this is the recommendation now...

anyone can help ?
thanks
 
Solution
Last try - see if attached is working for "31". Have changed the Java code to be as follows:

B4X:
    NFCUtils(final Activity pActivity) {
        mActivity = pActivity;
        mNfcAdapter = NfcAdapter.getDefaultAdapter(mActivity);
        if (Build.VERSION.SDK_INT < 31) {
            mPendingIntent = PendingIntent.getActivity(mActivity, 0,
                    new Intent(mActivity, mActivity.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
        } else {
       
            mPendingIntent = PendingIntent.getActivity(mActivity, 0,
                    new Intent(mActivity, mActivity.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 67108864);
        }  
    }

@agraham , please comment if I have it...

Zeev Goldstein

Well-Known Member
Licensed User
Longtime User
as i can't give up the security checks i make in activity_create to prevent illegal use or read i had to choose - make the checks or give up the random reads
i give up the random reads
i created a mechanism that the app loads, makes the check and if needed closes down
no read is done - or done but not processed

it is a small price but i'm happy to pay it
i just wanted to prevent the random reads and i see it is either impossible for my app or too complicated

had to give up unfortunately
my app is a sensitive critical financial app so there is no room for any mistake on my side

thank you for you help and patience
 
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
Zeev, this is where I am leaving it - last update. Take note of the code (using KVS) in the attached B4A project. I am using KVS to keep track of a "flag" that allows the app to allow / disallow a read of a banking card. See the toggle button at top left - you can change the UI as you like or change your code based on your assumptions on when to allow / disallow reading of the banking card. Toggle the togglebutton - it will then either return a read (read enabled) or return nothing (read disabled). Library files V1.04 attached.

Check.png


Sample code:


B4A - TapCard:
#Region  Project Attributes
    #ApplicationLabel: b4aTapCard
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: portrait
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Private xui As XUI
End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
                                                                         'MAKE SURE YOU ENABLE NFC ON YOUR DEVICE BEFORE SCANNING A CARD. THE APP WILL NOT PROMPT YOU TO ENABLE NFC CAPABILITY. YOU CAN ADD IT YOURSELF.
    Dim tapcard As TapCard                                               'declare TapCard
    Dim prevIntent As Intent                                             'see "If si.IsInitialized = False Or si = prevIntent Then Return"......
    Dim ips As InputStream                                               'declare InputStream
    Private Label1 As Label                                              'declare Label1 - it will display the infor returned in event "ips_scan_result(cardNumber As String, cardType As String, expireDate As String, cardHolderLastname As String, cardHolderFirstname As String, isNfcLocked As Boolean)"
    Dim mbm As Bitmap                                                    'declare bitmap that indicates to scan the card. It will be displayed when app is started and also if you click on Label1 after a scan
                                                                         'you can at any time scan a new card after you have scanned a card - no need to click on Lable1 to show the bitmap
    Private ImageView1 As ImageView                                      'imageview that will display the bitmap
    Private EditText1, EditText2 As EditText                                        'used to display the command / response between the card and the device - it is scrollable so that you can voew the entire comms between the card and the device

    Dim tgname As List                                                   'a list to hold the tagnames
    Dim tg As List                                                       'a list to hold the tags
    Dim tglength As List                                                 'a list to hold the tag lengths
    Dim tgvalue As List                                                  'a list to hold the tag values
    
    Dim kvs As KeyValueStore
    

    Private ToggleButton1 As ToggleButton
End Sub

Sub Activity_Create(FirstTime As Boolean)
    
    Activity.LoadLayout("Layout")
    
    If File.Exists(File.DirInternal, "read.kvs") Then
        Log("file exists")
    Else
        kvs.Initialize(File.DirInternal, "read.kvs")
        kvs.Put("flag", 0)
        Log("made a file")
        
    End If
    
    kvs.Initialize(File.DirInternal, "read.kvs")
    If 0 = kvs.Get("flag") Then
        tapcard.EnableRead = False
        ToggleButton1.Checked = False
    Else
        tapcard.EnableRead = True
        ToggleButton1.Checked = True
        
    End If
    
    
    Log("IN ACTIVITY_CREATE")
    tgname.Initialize                                                     'initialize an empty list for the tagnames
    tg.Initialize                                                         'initialise an empty list for the tags
    tglength.Initialize                                                   'initilaize an empty list for the tag lengths
    tgvalue.Initialize                                                    'initialize an empty list for the tag values
    

    Label1.Visible = False
    EditText1.Color = Colors.LightGray
    EditText2.Color = Colors.Cyan
    
    tapcard.Initialize("ips")                                             'initialize TapCard
    ips = File.OpenInput(File.DirAssets,"smartcard_list.txt")             'Load the lookup list as an inputstream for various cards from smartcard_list.txt in the asset folder
    mbm.Initialize(File.DirAssets, "tapimage.png")                        'load the bitmap into mbm
    ImageView1.Bitmap = mbm                                               'set the bitmap to be dispalyes by Imageview1
    ImageView1.Visible = True                                             'show the bitmap
    Label1.Visible = False                                                'hide the label
    EditText1.Visible = False                                             'hide the scrollable edittext
    EditText2.Visible = False
    
    tapcard.IPS = ips                                                     'pass the InputStream to the library - the library needs the inputstream from the text file.                                               '

    
End Sub

Sub Activity_Resume

    tgname.Clear                                                        'clear the list that holds the tag names
    tg.Clear                                                            'clear the list that holds the tags
    tglength.clear                                                      'clear the list that holds the tag lengths
    tgvalue.clear                                                       'clear the list that holds the tag values
    
    EditText1.Text = "YOU CAN SCROLL ME UP/DOWN TO VIEW ALL COMMANDS/RESPONSES" & CRLF & CRLF
    EditText2.Text = "YOU CAN SCROLL ME UP/DOWN TO VIEW ALL TAG INFO" & CRLF & CRLF

    Dim si As Intent = Activity.GetStartingIntent
    'check that the intent is a new intent
    If si.IsInitialized = False Or si = prevIntent Then Return            'no intent received or intent is the same as previous intent
    prevIntent = si                                                       'set previntent to the starting intent
    If si.Action.EndsWith("TECH_DISCOVERED") Or si.Action.EndsWith("NDEF_DISCOVERED") Or si.Action.EndsWith("TAG_DISCOVERED") Then   'check what action is available in the intent received
        If si.Action.EndsWith("TECH_DISCOVERED") Then                     'show a toast message of the action available in the intent received.           
            ToastMessageShow("TECH_DISCOVERED", False)
        Else If si.Action.EndsWith("NDEF_DISCOVERED") Then
            ToastMessageShow("NDEF_DISCOVERED", False)
        Else If si.Action.EndsWith("TAG_DISCOVERED") Then
            ToastMessageShow("TAG_DISCOVERED", False)
        Else
            ToastMessageShow("NOTHING_DISCOVERED", False)       
        End If
        Label1.Visible = True                                            'make label1 visible
        ImageView1.Visible = False                                       'hide imageview1
        EditText1.Visible = False                                        'hide edittext1
        EditText2.Visible = False
    End If

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

'Event that will be raised when a card has been scanned - it brings back the CardNumber, CardType, CardExpityDate, CardHolderLastName, CardHolderFirstName, if the card is NFC locked
Sub ips_scan_result(cardNumber As String, cardType As String, expireDate As String, cardHolderLastname As String, cardHolderFirstname As String, isNfcLocked As Boolean)
    Label1.Text = ""                         'set the text in label1.text to nothing
    ImageView1.Visible = False               'hide imageview1
    Label1.Visible = True                    'make labe11 visible

    'set the text of label1 to the values receive from the event
    Label1.Text = "CardNumber: " & cardNumber & CRLF & "cardType: " & cardType & CRLF & "expireDate: " & expireDate & CRLF  _
                  & "Card Holder Last Name: " & cardHolderLastname & CRLF & "Card Holder First Name : " & cardHolderFirstname _
                  & CRLF & "isNfcLocked : " & isNfcLocked
    EditText1.Visible = True       'make edittext1 visible.
    EditText2.Visible = True       'make edittext1 visible.
    
End Sub

'the commands and responses between the card and the device - it will be dispalyed in EditText1 (it is scrollable so that you can view all commands/responses
Sub ips_command_response(command As String, response As String)
    Log("COMMAND = " & command)                       'log command from device to the card in the B4A log
    Log("RESPONSE = " & response)                     'log response from the card to the device in the B4A log
    
    'set the command / response comms in edittext1
    'note that there are numerous commands sent / responses received from a single card scan - the code below just adds to the empty string so that you can see the entire conversation
    'EditeText1 will be "reset" to "" when a new scan occurs so that a new command/response string can be built.
    EditText1.Text = EditText1.Text & "COMMAND: " & CRLF & command & CRLF & "RESPONSE: " & response & CRLF & CRLF
    Log(" ")
    
    
End Sub

'this event bring back tagName, the Tag itself (HEX), the Tag length (HEX), and the Tag values (HEX) to the B4A project (from the library)
Sub ips_tag_data (tagname As String, tags As String, taglengths As String, tagvalues As String)

    EditText2.Visible = True                 'make edittext2 visible
    tgname.Add(tagname)                      'add a tag name
    tg.Add(tags)                             'add the tag
    tglength.Add(taglengths)                 'add the tag length
    tgvalue.Add(tagvalues)                   'add the tag value
    
End Sub

'this event will be raised once the card has been read - i.e all comms between the card and the device have been completed
Sub ips_scan_completed
    
    Log("In B4A and scan completed")                                                 'the card scan is completed
    Log("ATR = " & tapcard.CardATRValue)                                             'get the ATR of te card - it is used to lookup bank info in /Files/smarcard_list.txt
    Log("Possible Banks = " & tapcard.PossibleBankInfo)                              'get the possible banks that could have issued this card - it depends on the ATR read above
    'late arrivals that are added to the end of Label1 - late = only available in the wrapper once the card has been scanned and comms between
    'the card and the device are completed.
    Label1.Text = Label1.Text & CRLF & "ATR: " & tapcard.CardATRValue & CRLF & _     'get the ATR and add it to Label1
                                "Possible Banks: " & tapcard.PossibleBankInfo         'get possible Banks and add it to Label1
    
    
    For i = 0 To tgname.Size - 1                          'going to display all the tag names, tags, tag lengths, tag values in EditText2
        EditText2.Text = EditText2.Text & CRLF &"TagName: " &tgname.Get(i)
        EditText2.Text = EditText2.Text & CRLF & "Tag: " & tg.Get(i)
        EditText2.Text = EditText2.Text & CRLF & "TagLength: " & tglength.Get(i)
        EditText2.Text = EditText2.Text & CRLF & "TagValue: " & tgvalue.Get(i) & CRLF
    Next
    
    
End Sub

'these are hooks to the wrapper as the wrapper uses for eg onNewIntent, onResume, onPause and dont want to extend the wrapper with Activity
#If Java

    public void _onnewintent (android.content.Intent intent) {
        BA.Log("IN B4A ONNEWINTENT");
    }
    
    public void _onresume () {

    }   
    
    public void _onpause () {

    }   

#End If

Private Sub Label1_Click
    
    Label1.Visible = False                                              'hide label1
    ImageView1.Visible = True                                           'show imageview1
    EditText1.Visible = False                                           'hide edittext1
    EditText1.Text = ""                                                 'set edittext1.text to nothing
    
    EditText2.Visible = False                                           'hide edittext2
    EditText2.Text = ""                                                 'set edittext2.text to nothing
    
    tgname.Clear                                                        'clear the list that holds the tag names
    tg.Clear                                                            'clear the list that holds the tags
    tglength.clear                                                      'clear the list that holds the tag lengths
    tgvalue.clear                                                       'clear the list that holds the tag values
    
End Sub


Private Sub ToggleButton1_CheckedChange(Checked As Boolean)
    
    If ToggleButton1.Checked = False Then
        tapcard.EnableRead = False
        kvs.Initialize(File.DirInternal, "read.kvs")
        kvs.Put("flag", 0)
    Else
        tapcard.EnableRead = True
        kvs.Initialize(File.DirInternal, "read.kvs")
        kvs.Put("flag", 1)
    End If
    
End Sub

The method added is.....
B4X:
tapcard.EnableRead = False  'or True
.....but it comes with some overhead that you will have to handle such as what I have done in attached B4A project making use of KVS (KeyValueStore)

You need to ensure that your code enables NFC - I guess via an intent should the user device not have NFC enabled. But I guess you are past that hurdle already.
 

Attachments

  • TapCardV1.04.zip
    128.9 KB · Views: 78
  • b4aTapCard.zip
    167.1 KB · Views: 75
Upvote 0
Top