Search code examples
androidandroid-studioopenfiresmack

simple smack android client not working?


I am using this android source code, which is simple XMPP android client. I have installed Openfire locally and created a user, in GenyMotion I can connect to the created user after clicking login button, and I see the online user in openfire panel, I have also added two contact to contacts list in Genymotion, but when I continue debugging, I am getting this error:

    10/06 13:54:43: Launching app
    No apk changes detected since last installation, skipping installation of C:\Users\Davoud\Downloads\Compressed\Working_Chat_For_Niki\Chat\app\build\outputs\apk\app-debug.apk
    $ adb shell am force-stop com.mycompany.chat
    $ adb shell am start -n "com.mycompany.chat/com.mycompany.chat.ui.LoginActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
    Client not ready yet..Waiting for process to come online
    Waiting for process to come online
    Connected to process 13332 on device genymotion-preview___google_nexus_5x___7_0_0___api_24___1080x1920-192.168.30.101:5555
    D/Connect() Function: onCreate=>connecting....
    D/SMACK: SENT (0): <stream:stream xmlns='jabber:client' to='192.168.119.1' xmlns:stream='http://etherx.jabber.org/streams' version='1.0' xml:lang='en'>
    D/SMACK: RECV (0): <?xml version='1.0' encoding='UTF-8'?><stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" from="desktop-8s6k7ec" id="1t9ccdyqpq" xml:lang="en" version="1.0"><stream:features><starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"></starttls><mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><mechanism>PLAIN</mechanism><mechanism>ANONYMOUS</mechanism><mechanism>SCRAM-SHA-1</mechanism><mechanism>CRAM-MD5</mechanism><mechanism>DIGEST-MD5</mechanism></mechanisms><compression xmlns="http://jabber.org/features/compress"><method>zlib</method></compression><auth xmlns="http://jabber.org/features/iq-auth"/><register xmlns="http://jabber.org/features/iq-register"/></stream:features>
    D/ChatActivity: onServiceConnected
    D/xmpp: Connected!
    D/SMACK: SENT (0): <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='SCRAM-SHA-1'>biwsbj0zMjEscj07KiNwUSI3TiJ7ckVEfC15RDw3Sl80ZDxUWUxaYHFVTA==</auth>
    D/SMACK: RECV (0): <challenge xmlns="urn:ietf:params:xml:ns:xmpp-sasl">cj07KiNwUSI3TiJ7ckVEfC15RDw3Sl80ZDxUWUxaYHFVTGRmMmJmMDVhLTIxNzEtNGMwNi05ZDY5LTBlYTYzMDAyMTY3OSxzPWNzWVR5aXNRbnBycDh5aVpYNHpVdFEwSWNtb0JmM1k2LGk9NDA5Ng==</challenge>
    W/EGL_emulation: eglSurfaceAttrib not implemented
    W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0xdb25eec0, error=EGL_SUCCESS
    W/EGL_emulation: eglSurfaceAttrib not implemented
    W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0xda550560, error=EGL_SUCCESS
    D/SMACK: SENT (0): <response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>Yz1iaXdzLHI9OyojcFEiN04ie3JFRHwteUQ8N0pfNGQ8VFlMWmBxVUxkZjJiZjA1YS0yMTcxLTRjMDYtOWQ2OS0wZWE2MzAwMjE2NzkscD1KZCtLT3RUSWt0VGlFdnJYbXcxRnNlYjZ0UFk9</response>
    D/SMACK: RECV (0): <success xmlns="urn:ietf:params:xml:ns:xmpp-sasl">dj1pUFBqZGlyU0pnK0djbm1TZ1lCaU9oWEJLYkE9</success>
    D/SMACK: SENT (0): <stream:stream xmlns='jabber:client' to='192.168.119.1' xmlns:stream='http://etherx.jabber.org/streams' version='1.0' id='1t9ccdyqpq' xml:lang='en'>
    D/SMACK: RECV (0): <?xml version='1.0' encoding='UTF-8'?><stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" from="desktop-8s6k7ec" id="1t9ccdyqpq" xml:lang="en" version="1.0"><stream:features><compression xmlns="http://jabber.org/features/compress"><method>zlib</method></compression><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/><session xmlns="urn:ietf:params:xml:ns:xmpp-session"><optional/></session><sm xmlns='urn:xmpp:sm:2'/><sm xmlns='urn:xmpp:sm:3'/></stream:features>
    D/SMACK: SENT (0): <iq id='PhJm6-3' type='set'><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><resource>Smack</resource></bind></iq>
    D/SMACK: RECV (0): <iq type="result" id="PhJm6-3" to="desktop-8s6k7ec/1t9ccdyqpq"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><jid>321@desktop-8s6k7ec/Smack</jid></bind></iq>
    D/SMACK: SENT (0): <enable xmlns='urn:xmpp:sm:3' resume='true'/>
    D/SMACK: RECV (0): <enabled xmlns='urn:xmpp:sm:3'/>
    D/SMACK: User logged (0): 321@desktop-8s6k7ec:5222/Smack
    D/xmpp: Authenticated!
    D/SMACK: XMPPConnection authenticated (0)
    D/SMACK: SENT (0): <iq id='PhJm6-5' type='get'><query xmlns='jabber:iq:roster'></query></iq>
    I/LOGIN: Yey! We're connected to the Xmpp server!
    D/SMACK: RECV (0): <iq type="result" id="PhJm6-5" to="321@desktop-8s6k7ec/Smack"><query xmlns="jabber:iq:roster"/></iq>
    D/SMACK: SENT (0): <presence id='PhJm6-6'><c xmlns='http://jabber.org/protocol/caps' hash='sha-1' node='http://www.igniterealtime.org/projects/smack' ver='E6FpoDPmjMQ3i53V+HWh0YBrS7U='/></presence>
    E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
                      Process: com.mycompany.chat, PID: 13332
                      java.lang.RuntimeException: An error occurred while executing doInBackground()
                          at android.os.AsyncTask$3.done(AsyncTask.java:318)
                          at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
                          at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
                          at java.util.concurrent.FutureTask.run(FutureTask.java:242)
                          at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
                          at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
                          at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
                          at java.lang.Thread.run(Thread.java:761)
                       Caused by: java.lang.SecurityException: Permission Denial: opening provider com.android.providers.contacts.ContactsProvider2 from ProcessRecord{68c245f 13332:com.mycompany.chat/u0a71} (pid=13332, uid=10071) requires android.permission.READ_CONTACTS or android.permission.WRITE_CONTACTS
                          at android.os.Parcel.readException(Parcel.java:1683)
                          at android.os.Parcel.readException(Parcel.java:1636)
                          at android.app.ActivityManagerProxy.getContentProvider(ActivityManagerNative.java:4169)
                          at android.app.ActivityThread.acquireProvider(ActivityThread.java:5434)
                          at android.app.ContextImpl$ApplicationContentResolver.acquireUnstableProvider(ContextImpl.java:2267)
                          at android.content.ContentResolver.acquireUnstableProvider(ContentResolver.java:1515)
                          at android.content.ContentResolver.query(ContentResolver.java:514)
                          at android.content.ContentResolver.query(ContentResolver.java:472)
                          at com.mycompany.chat.ui.FriendsActivity$GetUser.doInBackground(FriendsActivity.java:67)
                          at com.mycompany.chat.ui.FriendsActivity$GetUser.doInBackground(FriendsActivity.java:54)
                          at android.os.AsyncTask$2.call(AsyncTask.java:304)
                          at java.util.concurrent.FutureTask.run(FutureTask.java:237)
                          at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243) 
                          at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 
                          at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
                          at java.lang.Thread.run(Thread.java:761) 
    I/Process: Sending signal. PID: 13332 SIG: 9
    Application terminated.

Solution

  • Add this to manifest:

    <uses-permission android:name="android.permission.READ_CONTACTS" />
    

    and in your activity ask permission for it (if sdk >= 23),

    @Override
    public void onCreate(Bundle b) {
        askPermission();    
    }
    
    public void askPermission(){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ContextCompat.checkSelfPermission(getActivity(),Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
                if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(),
                        Manifest.permission.READ_CONTACTS)) {
                    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
                    builder.setTitle("Contacts access needed");
                    builder.setPositiveButton(android.R.string.ok, null);
                    builder.setMessage("please confirm Contacts access");//TODO put real question
                    builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
                        @TargetApi(Build.VERSION_CODES.M)
                        @Override
                        public void onDismiss(DialogInterface dialog) {
                            requestPermissions(
                                    new String[]
                                            {Manifest.permission.READ_CONTACTS}
                                    , PERMISSION_REQUEST_CONTACT);
                        }
                    });
                    builder.show();
                } else {
                    // No explanation needed, we can request the permission.
                    ActivityCompat.requestPermissions(getActivity(),
                            new String[]{Manifest.permission.READ_CONTACTS},
                            PERMISSION_REQUEST_CONTACT);
    
                    // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
                    // app-defined int constant. The callback method gets the
                    // result of the request.
                }
            }
        }
    }
    
    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {
        switch (requestCode) {
            case PERMISSION_REQUEST_CONTACT: {
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
    
                    // permission granted
                } else {
                    //permission denied
                }
                return;
            }
        }
    }