Android Code Snippet Using StartActivityForResult with JavaObject

SubName: StartActivityForResult

Description: This code demonstrates how JavaObject can be used to call external APIs that should be called with Context.startActivityForResult.
Same implementation in a class: https://www.b4x.com/android/forum/threads/b4xpages-and-startactivityforresult.119176/post-745271

This code should be added to an Activity. You should also declare a process global variable named ion:
B4X:
Sub Process_Globals
   Private ion As Object
End Sub

B4X:
Sub ion_Event (MethodName As String, Args() As Object) As Object
'Args(0) = resultCode
'Args(1) = intent
Return Null
End Sub

Sub StartActivityForResult(i As Intent)
   Dim jo As JavaObject = GetBA
   ion = jo.CreateEvent("anywheresoftware.b4a.IOnActivityResult", "ion", Null)
   jo.RunMethod("startActivityForResult", Array As Object(ion, i))
End Sub

Sub GetBA As Object
   Dim jo As JavaObject
   Dim cls As String = Me
   cls = cls.SubString("class ".Length)
   jo.InitializeStatic(cls)
   Return jo.GetField("processBA")
End Sub

For example we can show the Ringtone picker with this code:
B4X:
Sub Activity_Create(FirstTime As Boolean)
   If FirstTime Then
     ShowPicker
   End If  
End Sub

Sub ShowPicker
   Dim i As Intent
   i.Initialize("android.intent.action.RINGTONE_PICKER", "")
   i.PutExtra("android.intent.extra.ringtone.TYPE", 1)
   StartActivityForResult(i)
End Sub


Sub ion_Event (MethodName As String, Args() As Object) As Object
   If Args(0) = -1 Then 'resultCode = RESULT_OK
     Dim i As Intent = args(1)
     Dim jo As JavaObject = i
     Dim uri As String = jo.RunMethod("getParcelableExtra", _
       Array As Object("android.intent.extra.ringtone.PICKED_URI"))
     Log(uri)
   End If
   Return Null
End Sub

Dependencies: JavaObject v1.20+

Tags: StartActivityForResult, OnActivityResult
 
Last edited:

bluedude

Well-Known Member
Licensed User
Longtime User
Could you provide a sample for the contactlist? I only target Android 4.x so I guess that will always work.
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
1. Add the following permission to the manifest editor:
B4X:
AddPermission(android.permission.READ_CONTACTS)
2. Use the following code:
B4X:
Sub Activity_Click
   Dim i As Intent
   i.Initialize(i.ACTION_PICK, "content://com.android.contacts/contacts")
   StartActivityForResult(i)
End Sub

Sub ion_Event (MethodName As String, Args() As Object) As Object
   If Args(0) = -1 Then 'resultCode = RESULT_OK
     Dim i As Intent = args(1)
     Dim id As String = i.GetData.SubString(i.GetData.LastIndexOf("/") + 1)
     Dim cu As ContactsUtils
     cu.Initialize
     Log(cu.GetNameFromId(id))
   End If
   Return Null
End Sub

Add the following sub to ContactsUtils:
B4X:
Public Sub GetNameFromId (id As String) As String
   Dim crsr As Cursor = cr.Query(dataUri, Array As String("contact_id", "display_name"), "contact_id = ?", _
     Array As String(id), "")
   Dim name As String
   If crsr.RowCount = 0 Then
     Log("Contact not found: " & id)
   Else
     crsr.Position = 0
     name = crsr.GetString2(1)
   End If
   crsr.Close
   Return name
End Sub
 

bluedude

Well-Known Member
Licensed User
Longtime User
Right, will try it! Don't want to create my own activities for contact picking.
 

bluedude

Well-Known Member
Licensed User
Longtime User
Works great but wondering how to get the email address of the user? Tried a few things but could not get it.
 

geodesic

New Member
Licensed User
Longtime User
I may be missing something obvious, but I am still a novice and trying to figure out how values are reflected between Java and b4a. I had a need for an intent with a return, so I copied this code (almost) except I substituted ACCOUNT_PICKER instead of RINGTONE_PICKER.

My first attempt to read the return value failed, using the code:
B4X:
account = jo.RunMethod("getStringExtra", Array As Object("android.accounts.AccountManager.KEY_ACCOUNT_NAME"))

The result came back null. Strange, as eventually I figured out how to stop in the debugger and analyze the variables which clearly showed the data in jo.mExtras.mMap.mArray

I then changed the code to:

B4X:
 account = jo.RunMethod("getStringExtra", Array As Object("authAccount"))

And everything worked.

I am very puzzled why this is, since android.accounts.AccountManager.KEY_ACCOUNT_NAME is defined with constant value "authAccount". Is this because:

A) There is something wrong with my code
B) Because of a bug in b4a
C) Because there is a library missing and b4a can't evaluate the variable
D) Something else that I am not considering

If someone can answer this and explain to me what I should have done to save myself several hours of struggling it would be helpful for my education.

If the answer is C, how can I know which android.* libraries are included by default and which ones are not? There certainly were not any warning messages displayed.

Thank you for any assistance.
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
You are confusing the constant name (variable name) with the actual value. The value is "authAccount". You have passed a different string, so it didn't work.

Note that you can get the constant value with:
B4X:
Dim v As JavaObject
Dim constValue As String = v.InitializeStatic("android.accounts.AccountManager").GetField("KEY_ACCOUNT_NAME")
 

TheMightySwe

Active Member
Licensed User
Longtime User
Hi,

We have a java app that connects to a Cardterminal that has the name "se.iqpd.checkout.companion". We start that in B4A with the following code.

B4X:
Dim ISMP_Intent As Intent
    Dim InstalledPackages As PackageManager
    ISMP_Intent = InstalledPackages.GetApplicationIntent("se.iqpd.checkout.companion")
    ISMP_Intent.PutExtra("JobId","31271")
    ISMP_Intent.PutExtra("TransactionType","Purchase")
    ISMP_Intent.PutExtra("Amount",NumberFormat2(SubTotal_Double-SubTotal_Discount_Double,1,2,2,False))
    StartActivityForResult(ISMP_Intent)

We send the return with following JAVA-code

B4X:
Intent output = new Intent();
            output.putExtra("RESULT", RESULT_OK);
[....] ' Lots of  otherresultdata that we cant post because of confidentiallity agreement  
            getParent().setResult(Activity.RESULT_OK, output);
            finish();


But in B4A we get a error, nothing returns.

main_companion_event (B4A line: 1984)
ResultCode = Args(0)
java.lang.ArrayIndexOutOfBoundsException: length=0; index=0
at se.iqpd.checkout.plus.main._companion_event(main.java:4069)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:175)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:159)
at anywheresoftware.b4j.object.JavaObject$1.invoke(JavaObject.java:191)
at $Proxy0.toString(Native Method)
at java.lang.String.valueOf(String.java:1649)
at anywheresoftware.b4a.debug.Debug.objectToString(Debug.java:384)
at anywheresoftware.b4a.debug.Debug.writeGlobals(Debug.java:303)
at anywheresoftware.b4a.debug.Debug.sendBPData(Debug.java:284)
at anywheresoftware.b4a.debug.Debug.access$9(Debug.java:279)
at anywheresoftware.b4a.debug.Debug$1.run(Debug.java:256)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at anywheresoftware.b4a.Msgbox.waitForMessage(Msgbox.java:200)
at anywheresoftware.b4a.Msgbox.debugWait(Msgbox.java:158)
at anywheresoftware.b4a.debug.Debug.wait(Debug.java:213)
at anywheresoftware.b4a.debug.Debug.reachBP(Debug.java:260)
at anywheresoftware.b4a.debug.Debug.ShouldStop(Debug.java:232)
at se.iqpd.checkout.plus.main._unitevents_batterychanged(main.java:23572)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:175)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:159)
at anywheresoftware.b4a.phone.PhoneEvents$ActionHandler$1.run(PhoneEvents.java:321)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5279)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
at dalvik.system.NativeStart.main(Native Method)


Why is that, anyone knows?

// TMS
 
Last edited:

TheMightySwe

Active Member
Licensed User
Longtime User
Hi,

StartActivityForResult code seems to call up the "Complete Action Using" - dialog after 4.30 update, anyone know why, and what to do to suppress it?

It happens in all calls to StartActivityForResult in my app.


Just an example

B4X:
Sub StartEmail

    Dim Email_Intent As Intent
    Dim InstalledPackages As PackageManager
    Email_Intent = InstalledPackages.GetApplicationIntent("com.google.android.email")

    StartActivityForResult(Email_Intent, "EMail")

End Sub
 

b4auser1

Well-Known Member
Licensed User
Longtime User
I used the code from the thread to pick a contact from Contacts intent and it worked good until Android 5.1.
On Nexus 5 with Android 5.1 it shows contacts list, but after selecting a contact nothing happened.
I checked the same apk on device with Android 4.4.2, 5.0.2 and there everything is Ok.
 

b4auser1

Well-Known Member
Licensed User
Longtime User
ion_Event is not called under Android 5.1
only "onActivityResult: IOnActivityResult was released" messaged is in Log.
 
Top