Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Mobile and Embedded
  4. Calling Java method from within Qt yields exception

Calling Java method from within Qt yields exception

Scheduled Pinned Locked Moved Solved Mobile and Embedded
16 Posts 5 Posters 1.4k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Bremenpl

    @jsulm i will check that, but could you elaborate why does the example code work?

    jsulmJ Offline
    jsulmJ Offline
    jsulm
    Lifetime Qt Champion
    wrote on last edited by jsulm
    #6

    @Bremenpl said in Calling Java method from within Qt yields exception:

    but could you elaborate why does the example code work?

    Take a look at this (from the example):

    A NotificationClient object is exposed to the QML in the main source file, main.cpp:
    
    QQuickView view;
    
    NotificationClient *notificationClient = new NotificationClient(&view);
    view.engine()->rootContext()->setContextProperty(QLatin1String("notificationClient"),
                                                         notificationClient);
    

    As you can see in the example an instance of NotificationClient is created, so m_instance is set. I guess you don't have this part of the code in your project?

    https://forum.qt.io/topic/113070/qt-code-of-conduct

    B 2 Replies Last reply
    2
    • jsulmJ jsulm

      @Bremenpl said in Calling Java method from within Qt yields exception:

      but could you elaborate why does the example code work?

      Take a look at this (from the example):

      A NotificationClient object is exposed to the QML in the main source file, main.cpp:
      
      QQuickView view;
      
      NotificationClient *notificationClient = new NotificationClient(&view);
      view.engine()->rootContext()->setContextProperty(QLatin1String("notificationClient"),
                                                           notificationClient);
      

      As you can see in the example an instance of NotificationClient is created, so m_instance is set. I guess you don't have this part of the code in your project?

      B Offline
      B Offline
      Bremenpl
      wrote on last edited by
      #7

      @jsulm no, i dont... Thank you very much. Will check this asap.

      lprzenioslo.zut.edu.pl

      1 Reply Last reply
      0
      • jsulmJ jsulm

        @Bremenpl said in Calling Java method from within Qt yields exception:

        but could you elaborate why does the example code work?

        Take a look at this (from the example):

        A NotificationClient object is exposed to the QML in the main source file, main.cpp:
        
        QQuickView view;
        
        NotificationClient *notificationClient = new NotificationClient(&view);
        view.engine()->rootContext()->setContextProperty(QLatin1String("notificationClient"),
                                                             notificationClient);
        

        As you can see in the example an instance of NotificationClient is created, so m_instance is set. I guess you don't have this part of the code in your project?

        B Offline
        B Offline
        Bremenpl
        wrote on last edited by
        #8

        @jsulm But here is the thing: In some weird way that is not fully understandable to me, this java class is connected with QML, that in my opinion should have nothing to do with anything related to this topic... It seems like somehow the cpp class name NotificationClient being the same as the java class name is not an accident? Is there a way to disengage all those hard coded components from this example?

        lprzenioslo.zut.edu.pl

        jsulmJ 1 Reply Last reply
        0
        • B Bremenpl

          @jsulm But here is the thing: In some weird way that is not fully understandable to me, this java class is connected with QML, that in my opinion should have nothing to do with anything related to this topic... It seems like somehow the cpp class name NotificationClient being the same as the java class name is not an accident? Is there a way to disengage all those hard coded components from this example?

          jsulmJ Offline
          jsulmJ Offline
          jsulm
          Lifetime Qt Champion
          wrote on last edited by
          #9

          @Bremenpl Yes, you're right the code I pasted is C++. I'm not an JNI expert, so I don't know where the instance is created. All I know is what the error message says: there is no instance.
          "F m.company.mr: java_vm_ext.cc:542] JNI DETECTED ERROR IN APPLICATION: JNI GetStaticMethodID called with pending exception java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object com.company.mri.NotificationClient.getSystemService(java.lang.String)' on a null object reference"

          Maybe somebody else has an idea what is missing in your project.

          Does the example application work?

          https://forum.qt.io/topic/113070/qt-code-of-conduct

          B 1 Reply Last reply
          0
          • jsulmJ jsulm

            @Bremenpl Yes, you're right the code I pasted is C++. I'm not an JNI expert, so I don't know where the instance is created. All I know is what the error message says: there is no instance.
            "F m.company.mr: java_vm_ext.cc:542] JNI DETECTED ERROR IN APPLICATION: JNI GetStaticMethodID called with pending exception java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object com.company.mri.NotificationClient.getSystemService(java.lang.String)' on a null object reference"

            Maybe somebody else has an idea what is missing in your project.

            Does the example application work?

            B Offline
            B Offline
            Bremenpl
            wrote on last edited by
            #10

            @jsulm Yes, the example works perfectly well. But my problem is that I am unable to figure out what is necessary in that example and what is not, since it is not described. For instance, I dont need to export any methods to the QML side. I also have no clue either the cpp NotificationClient class has the same name as java class for a reason, or it is a coincidence. At last, after you have suggested me what is wrong, I dont know how to create the java class instance via cpp without doing any unnecessarily operations on QML (or furthermore, creating an additional cpp class just for this end).

            lprzenioslo.zut.edu.pl

            B 1 Reply Last reply
            0
            • B Bremenpl

              @jsulm Yes, the example works perfectly well. But my problem is that I am unable to figure out what is necessary in that example and what is not, since it is not described. For instance, I dont need to export any methods to the QML side. I also have no clue either the cpp NotificationClient class has the same name as java class for a reason, or it is a coincidence. At last, after you have suggested me what is wrong, I dont know how to create the java class instance via cpp without doing any unnecessarily operations on QML (or furthermore, creating an additional cpp class just for this end).

              B Offline
              B Offline
              Bremenpl
              wrote on last edited by Bremenpl
              #11

              So I am just bumping the topic since it feels like I am close (thanks @jsulm). I would really appreciate anyone explaining me the magic happening in that android notofication example (about the namimg and everything)...

              lprzenioslo.zut.edu.pl

              L 1 Reply Last reply
              0
              • B Bremenpl

                So I am just bumping the topic since it feels like I am close (thanks @jsulm). I would really appreciate anyone explaining me the magic happening in that android notofication example (about the namimg and everything)...

                L Offline
                L Offline
                LtKoerschgen
                wrote on last edited by
                #12

                @Bremenpl I was facing the same problem as you. Maybe my solution is still valuable for you or anyone else reading this thread.

                First of all, also for me the notification example was working without any problems. The above mentioned code snipped

                NotificationClient *notificationClient = new NotificationClient(&view);
                view.engine()->rootContext()->setContextProperty(QLatin1String("notificationClient"),
                                                                     notificationClient);
                

                relates to the C++ class NotificationClient used in the example. For me it is really a disadvantage of the notification example to name the C++ class the same way as the Java class. This way it is more confusing to distinguish between the Java class and the C++ class.

                However, like @Bremenpl I also wanted to apply the same principle of calling Java code to my own project. I also was running into the error:

                called with pending exception java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object com.company.mri.NotificationClient.getSystemService(java.lang.String)' on a null object reference
                

                I checked the notification example and added some debug output to the Java class:

                public NotificationClient()
                    {
                        Log.i("NotificationClient", "Set instance");
                        m_instance = this;
                    }
                

                The debug output was shown in the console the QtCreator. I did the same for my own project but there was no debug output. So the static instance of my Java class never has been set. I found a hint to the solution here: http://schorsch.efi.fh-nuernberg.de/roettger/index.php/QtOnAndroid/AppObj
                There it is said that you need to provide an AndroidManifest.xml for the Java class. I did so. My file looks something like this:

                <?xml version="1.0"?>
                <manifest package="org.qtproject.example.myprojectname" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto">
                    <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/>
                    <application android:icon="@drawable/icon" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="Project_Label">
                        <activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|locale|fontScale|keyboard|keyboardHidden|navigation" android:name="org.qtproject.example.myprojectname.MyJavaClassName" android:label="JNI Caller" android:screenOrientation="unspecified">
                
                        </activity>
                    </application>
                    <!-- <supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/> -->
                    <!-- %%INSERT_PERMISSIONS -->
                    <uses-permission android:name="android.permission.INTERNET"/>
                    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
                    <!-- %%INSERT_FEATURES -->
                </manifest>
                

                You can basically copy the AndroidManifest.xml from the Notification example and adapt the package and activity name to fit your project's names.

                After adding this file to my own project (OTHER_FILES section in the pro file) and recompiling the project I saw my debug output in the console and was able to run my Java code without running into the NullPointerException! :-)

                B 1 Reply Last reply
                1
                • L LtKoerschgen

                  @Bremenpl I was facing the same problem as you. Maybe my solution is still valuable for you or anyone else reading this thread.

                  First of all, also for me the notification example was working without any problems. The above mentioned code snipped

                  NotificationClient *notificationClient = new NotificationClient(&view);
                  view.engine()->rootContext()->setContextProperty(QLatin1String("notificationClient"),
                                                                       notificationClient);
                  

                  relates to the C++ class NotificationClient used in the example. For me it is really a disadvantage of the notification example to name the C++ class the same way as the Java class. This way it is more confusing to distinguish between the Java class and the C++ class.

                  However, like @Bremenpl I also wanted to apply the same principle of calling Java code to my own project. I also was running into the error:

                  called with pending exception java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object com.company.mri.NotificationClient.getSystemService(java.lang.String)' on a null object reference
                  

                  I checked the notification example and added some debug output to the Java class:

                  public NotificationClient()
                      {
                          Log.i("NotificationClient", "Set instance");
                          m_instance = this;
                      }
                  

                  The debug output was shown in the console the QtCreator. I did the same for my own project but there was no debug output. So the static instance of my Java class never has been set. I found a hint to the solution here: http://schorsch.efi.fh-nuernberg.de/roettger/index.php/QtOnAndroid/AppObj
                  There it is said that you need to provide an AndroidManifest.xml for the Java class. I did so. My file looks something like this:

                  <?xml version="1.0"?>
                  <manifest package="org.qtproject.example.myprojectname" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto">
                      <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/>
                      <application android:icon="@drawable/icon" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="Project_Label">
                          <activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|locale|fontScale|keyboard|keyboardHidden|navigation" android:name="org.qtproject.example.myprojectname.MyJavaClassName" android:label="JNI Caller" android:screenOrientation="unspecified">
                  
                          </activity>
                      </application>
                      <!-- <supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/> -->
                      <!-- %%INSERT_PERMISSIONS -->
                      <uses-permission android:name="android.permission.INTERNET"/>
                      <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
                      <!-- %%INSERT_FEATURES -->
                  </manifest>
                  

                  You can basically copy the AndroidManifest.xml from the Notification example and adapt the package and activity name to fit your project's names.

                  After adding this file to my own project (OTHER_FILES section in the pro file) and recompiling the project I saw my debug output in the console and was able to run my Java code without running into the NullPointerException! :-)

                  B Offline
                  B Offline
                  Bremenpl
                  wrote on last edited by
                  #13

                  @LtKoerschgen You are right about all symptoms. I also agree with this:

                  For me it is really a disadvantage of the notification example to name the C++ class the same way as the Java class. This way it is more confusing to distinguish between the Java class and the C++ class.
                  

                  Very poor design, especially misleading for someone who doesn't know this API (like me). I was trying to figure out for a while either the naming has anything to do with this.

                  I will also leave my extended solution in case anyone needs it:

                  package com.company.appname;
                  
                  import android.app.Notification;
                  import android.app.NotificationChannel;
                  import android.app.NotificationManager;
                  import android.content.Context;
                  import android.os.Build;
                  
                  public class NotificationClient
                  {
                  	private static final String m_channelId = "channel";
                  
                  	public static void notify(Context context, String title, String body)
                  	{
                  		Notification.Builder m_builder;
                  
                  		if (Build.VERSION.SDK_INT >= 26)
                  		{
                  			createChannel(context);
                  			m_builder = new Notification.Builder(context, m_channelId);
                  		}
                  	    else
                  		{
                  			m_builder = new Notification.Builder(context);
                  		}
                  
                  	    NotificationManager m_notificationManager = (NotificationManager)
                  		    context.getSystemService(Context.NOTIFICATION_SERVICE);
                  
                  		m_builder.setContentTitle(title);
                  		m_builder.setContentText(body);
                  		m_builder.setShowWhen(true);
                  
                  		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
                  		{
                  			m_builder.setSmallIcon(R.drawable.icon_trans);
                  		}
                  	    else
                  		{
                  			m_builder.setSmallIcon(R.drawable.icon);
                  		}
                  
                  		m_notificationManager.notify(1, m_builder.build());
                  	}
                  
                  	private static void createChannel(Context context)
                  	{
                  		NotificationChannel channel = new NotificationChannel(
                  		    m_channelId, "General", NotificationManager.IMPORTANCE_HIGH);
                  		channel.setDescription("The general channel");
                  		channel.enableVibration(true);
                  
                  		NotificationManager notificationManager = (NotificationManager)
                  		    context.getSystemService(Context.NOTIFICATION_SERVICE);
                  		notificationManager.createNotificationChannel(channel);
                  	}
                  }
                  

                  lprzenioslo.zut.edu.pl

                  Pablo J. RoginaP 1 Reply Last reply
                  1
                  • W Offline
                    W Offline
                    Wim van der Meer
                    wrote on last edited by
                    #14

                    I was having the same problem, and this thread helped me to solve it.

                    The only thing you need to do is to change the android:name attribute in the <activity> tag inside the AndroidManifest.xml file. This name needs to be your package name followed by the class name, so for the OP it needs to be android:name="com.company.mri.NotificationClient"

                    B 1 Reply Last reply
                    1
                    • B Bremenpl

                      @LtKoerschgen You are right about all symptoms. I also agree with this:

                      For me it is really a disadvantage of the notification example to name the C++ class the same way as the Java class. This way it is more confusing to distinguish between the Java class and the C++ class.
                      

                      Very poor design, especially misleading for someone who doesn't know this API (like me). I was trying to figure out for a while either the naming has anything to do with this.

                      I will also leave my extended solution in case anyone needs it:

                      package com.company.appname;
                      
                      import android.app.Notification;
                      import android.app.NotificationChannel;
                      import android.app.NotificationManager;
                      import android.content.Context;
                      import android.os.Build;
                      
                      public class NotificationClient
                      {
                      	private static final String m_channelId = "channel";
                      
                      	public static void notify(Context context, String title, String body)
                      	{
                      		Notification.Builder m_builder;
                      
                      		if (Build.VERSION.SDK_INT >= 26)
                      		{
                      			createChannel(context);
                      			m_builder = new Notification.Builder(context, m_channelId);
                      		}
                      	    else
                      		{
                      			m_builder = new Notification.Builder(context);
                      		}
                      
                      	    NotificationManager m_notificationManager = (NotificationManager)
                      		    context.getSystemService(Context.NOTIFICATION_SERVICE);
                      
                      		m_builder.setContentTitle(title);
                      		m_builder.setContentText(body);
                      		m_builder.setShowWhen(true);
                      
                      		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
                      		{
                      			m_builder.setSmallIcon(R.drawable.icon_trans);
                      		}
                      	    else
                      		{
                      			m_builder.setSmallIcon(R.drawable.icon);
                      		}
                      
                      		m_notificationManager.notify(1, m_builder.build());
                      	}
                      
                      	private static void createChannel(Context context)
                      	{
                      		NotificationChannel channel = new NotificationChannel(
                      		    m_channelId, "General", NotificationManager.IMPORTANCE_HIGH);
                      		channel.setDescription("The general channel");
                      		channel.enableVibration(true);
                      
                      		NotificationManager notificationManager = (NotificationManager)
                      		    context.getSystemService(Context.NOTIFICATION_SERVICE);
                      		notificationManager.createNotificationChannel(channel);
                      	}
                      }
                      
                      Pablo J. RoginaP Offline
                      Pablo J. RoginaP Offline
                      Pablo J. Rogina
                      wrote on last edited by
                      #15

                      @Bremenpl said in Calling Java method from within Qt yields exception:

                      I will also leave my extended solution in case anyone needs it

                      Thanks for sharing. In addition, would you mind marking your post as solved?

                      Upvote the answer(s) that helped you solve the issue
                      Use "Topic Tools" button to mark your post as Solved
                      Add screenshots via postimage.org
                      Don't ask support requests via chat/PM. Please use the forum so others can benefit from the solution in the future

                      1 Reply Last reply
                      0
                      • W Wim van der Meer

                        I was having the same problem, and this thread helped me to solve it.

                        The only thing you need to do is to change the android:name attribute in the <activity> tag inside the AndroidManifest.xml file. This name needs to be your package name followed by the class name, so for the OP it needs to be android:name="com.company.mri.NotificationClient"

                        B Offline
                        B Offline
                        Bremenpl
                        wrote on last edited by
                        #16

                        @Wim-van-der-Meer thanks for info. For what end is this change needed?

                        lprzenioslo.zut.edu.pl

                        1 Reply Last reply
                        0

                        • Login

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt Extensions
                        • Unsolved