Android Question Problem with B4A map

wes58

Active Member
Licensed User
I am trying to write a function in Java to get a Notification Channel.
The code is:
B4X:
Sub GetNotifChannelMap(channelID As String) As String
    Dim Channel As JavaObject
    Dim channelObject As  Object    '
    Dim m As Map
    m.Initialize
    Channel.InitializeContext
    channelObject = Channel.RunMethod("mGetNotifChannel", Array(channelID))
'    m = Channel.RunMethod("mGetNotifChannel", Array(channelID))      <<<< get the same error if trying like this
    Log(channelObject)
    m = channelObject         <<< error here
    Log(m)
End Sub

#if JAVA
import android.content.Context;
import android.app.NotificationManager;
import android.app.NotificationChannel;
import android.os.Build;
import java.util.List;
import android.net.Uri;
import anywheresoftware.b4a.objects.collections.Map;

public anywheresoftware.b4a.objects.collections.Map mGetNotifChannel(String channelId){
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        Context context = BA.applicationContext;   
        NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        NotificationChannel channel =  notificationManager.getNotificationChannel(channelId);
        String Id = channel.getId();
        int importance = channel.getImportance();
        int lightcolor = channel.getLightColor();
        Boolean shVibrate = channel.shouldVibrate();
        Boolean shShowLight = channel.shouldShowLights();
        Uri sound = channel.getSound();
        anywheresoftware.b4a.objects.collections.Map map = new anywheresoftware.b4a.objects.collections.Map();
        map.Initialize();
        map.Put("Id", Id);
        map.Put("sound", sound);
        map.Put("Importance", importance);
        map.Put("lightcolor", lightcolor);
        map.Put("shouldVibrate", shVibrate);
        map.Put("shShowLight", shShowLight);
        return map; 
    }
    return null;
}
#End If
The problem is return value from the java function - map.
If I assign return value to object it works fine, until I try to get the correct values - it shows in the log as (MyMap).
But then, I want to get the map out of this object and I get the following error.
If I assign return value directly to map I get the same error.

B4X:
(MyMap) {Id=chBank, sound=content://media/internal/audio/media/148, Importance=4, lightcolor=-256, shouldVibrate=true, shShowLight=true}

java.lang.ClassCastException: anywheresoftware.b4a.objects.collections.Map cannot be cast to anywheresoftware.b4a.objects.collections.Map$MyMap
    at b4a.example3.main._getnotifchannelmap(main.java:1261)
    at b4a.example3.main._btn1_click(main.java:757)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:196)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:180)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:176)
    at anywheresoftware.b4a.objects.ViewWrapper$1.onClick(ViewWrapper.java:80)
    at android.view.View.performClick(View.java:7352)
    at android.widget.TextView.performClick(TextView.java:14177)
    at android.view.View.performClickInternal(View.java:7318)
    at android.view.View.access$3200(View.java:846)
    at android.view.View$PerformClick.run(View.java:27801)
    at android.os.Handler.handleCallback(Handler.java:873)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7032)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965)
I tried different combinations but always get this error:
How can I convert object to map?
 

wes58

Active Member
Licensed User
B4X:
return map.getObject();
Ok. On the first try, I got this error message during compilation:
B4X:
src\b4a\example3\main.java:2694: error: incompatible types: MyMap cannot be converted to Map
        return map.getObject();
So, what I did then, is changed return parameter in java function declaration from anywheresoftware.b4a.objects.collections.Map to Object:
B4X:
public Object mGetNotifChannel(String channelId){
...
...
  return map.getObject();
}
And in the sub I could use map:
B4X:
Sub GetNotifChannelMap(channelID As String) As String
    Dim Channel As JavaObject
    Dim m As Map
    m.Initialize
    Channel.InitializeContext
    m = Channel.RunMethod("mGetNotifChannel", Array(channelID))
    Log(m)
    Log("m " & m.GetKeyAt(0) & " " & m.GetValueAt(0))
End Sub
Now the question is, why I had to change both things to get map:
public Object mGetNotifChannel(String channelId){
return map.getObject();
During compilation: MyMap can't be converted to Map. So return value is changed to Object. But in B4A sub this return value (Object) is happy to be assigned to map. So confusing!

I don't know whether you can, or maybe Erel could explain this?

Thanks for your help.
 

wes58

Active Member
Licensed User
Why aren't you using NB6?
As far as I can see NB6 doesn't have a function getNotificationChannel() and getNotificationChannels(). Unless I don't have the latest NB6.bas?
I was going to add it in my thread in Code Snippets.
 

Erel

Administrator
Staff member
Licensed User
These methods are indeed not implemented in NB6.

I don't know whether you can, or maybe Erel could explain this?
It is related to Map being a wrapper object. JavaObject.RunMethod returns an Object. In such cases the compiler expects the Object type to be the wrapped type instead of the wrapper.

Notes:
1. Don't use GetKeyAt / GetValueAt.
2. No reason to initialize the map and then assign a new value anyway.
B4X:
Dim m As Map = Channel.RunMethod("mGetNotifChannel", Array(channelID))
 

wes58

Active Member
Licensed User
These methods are indeed not implemented in NB6.


It is related to Map being a wrapper object. JavaObject.RunMethod returns an Object. In such cases the compiler expects the Object type to be the wrapped type instead of the wrapper.

Notes:
1. Don't use GetKeyAt / GetValueAt.
2. No reason to initialize the map and then assign a new value anyway.
B4X:
Dim m As Map = Channel.RunMethod("mGetNotifChannel", Array(channelID))
I used GetKeyAt/GetValueAt when I was testing it.
I use value = map.Get(Key) to get a setting with specific Key.
I have posted my code in Code Snippets now.
I guess, I can remove initialization of the map.

Thanks for your help.
 
Top