skip to Main Content

I am trying to make an app that will access my phone’s contact list then pick a contact and show the name, number, id, and the display picture.
i can access contact . when I press the addFab button it shows my phones contactlist but when I pick a contact using the cursor the app crashes. I have also tried with a physical phone but same result.
I am getting this ERROR:

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.sosandvideo, PID: 11666
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=2, result=-1, data=Intent { dat=content://com.android.contacts/contacts/lookup/0r2-2C/2 flg=0x1 }} to activity {com.example.sosandvideo/com.example.sosandvideo.MainActivity}: android.database.sqlite.SQLiteException: near "2": syntax error (code 1 SQLITE_ERROR): , while compiling: SELECT phonetic_name, status_updates.status_res_package AS status_res_package, custom_ringtone, contacts_status_updates.status_ts AS contact_status_ts, account_type, data_version, photo_file_id, contacts_status_updates.status_res_package AS contact_status_res_package, group_sourceid, display_name_alt, sort_key_alt, presence.mode AS mode, 0 AS last_time_used, starred, contacts_status_updates.status_label AS contact_status_label, has_phone_number, presence.chat_capability AS chat_capability, raw_contact_id, carrier_presence, contact_last_updated_timestamp, res_package, photo_uri, data_sync4, phonebook_bucket, 0 AS times_used, display_name, sort_key, data_sync1, version, data_sync2, data_sync3, photo_thumb_uri, status_updates.status_label AS status_label, agg_presence.mode AS contact_presence, in_default_directory, 0 AS times_contacted, _id, account_type_and_data_set, name_raw_contact_id, status_updates.status AS status, phonebook_bucket_alt, 0 AS last_time_contacted, pinned, is_primary, photo_id, contact_id, agg_presence.chat_capability AS contact_chat_capability, contacts_status_updates.status_icon AS contact_status_icon, in_visible_group, phonebook_label, account_name, display_name_source, data9, dirty, sourceid, phonetic_name_style, send_to_voicemail, data8, lookup, data7, data6, phonebook_label_alt, data5, is_super_primary, data4, data3, data2, data1, data_set, contacts_status_updates.status AS contact_status, backup_id, preferred_phone_account_component_name, raw_contact_is_user_profile, status_updates.status_ts AS status_ts, data10, preferred_phone_account_id, data12, mimetype, status_updates.status_icon AS status_icon, data11, data14, data13, hash_id, data15 FROM view_data data LEFT OUTER JOIN agg_presence ON (contact_id = agg_presence.presence_contact_id) LEFT OUTER JOIN status_updates contacts_status_updates ON (status_update_id=contacts_status_updates.status_update_data_id) LEFT OUTER JOIN presence ON (presence_data_id=data._id) LEFT OUTER JOIN status_updates ON (status_updates.status_update_data_id=data._id) LEFT OUTER JOIN (SELECT 0 as STAT_DATA_ID,0 as x_times_used, 0 as x_last_time_used,0 as times_used, 0 as last_time_used where 0) as data_usage_stat ON (STAT_DATA_ID=data._id) WHERE (1 AND mimetype_id=5) AND (contact_id 2)
    at android.app.ActivityThread.deliverResults(ActivityThread.java:5015)
    at android.app.ActivityThread.handleSendResult(ActivityThread.java:5056)
    at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:51)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:223)
    at android.app.ActivityThread.main(ActivityThread.java:7656)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Caused by: android.database.sqlite.SQLiteException: near "2": syntax error (code 1 SQLITE_ERROR): , while compiling: SELECT phonetic_name, status_updates.status_res_package AS status_res_package, custom_ringtone, contacts_status_updates.status_ts AS contact_status_ts, account_type, data_version, photo_file_id, contacts_status_updates.status_res_package AS contact_status_res_package, group_sourceid, display_name_alt, sort_key_alt, presence.mode AS mode, 0 AS last_time_used, starred, contacts_status_updates.status_label AS contact_status_label, has_phone_number, presence.chat_capability AS chat_capability, raw_contact_id, carrier_presence, contact_last_updated_timestamp, res_package, photo_uri, data_sync4, phonebook_bucket, 0 AS times_used, display_name, sort_key, data_sync1, version, data_sync2, data_sync3, photo_thumb_uri, status_updates.status_label AS status_label, agg_presence.mode AS contact_presence, in_default_directory, 0 AS times_contacted, _id, account_type_and_data_set, name_raw_contact_id, status_updates.status AS status, phonebook_bucket_alt, 0 AS last_time_contacted, pinned, is_primary, photo_id, contact_id, agg_presence.chat_capability AS contact_chat_capability, contacts_status_updates.status_icon AS contact_status_icon, in_visible_group, phonebook_label, account_name, display_name_source, data9, dirty, sourceid, phonetic_name_style, send_to_voicemail, data8, lookup, data7, data6, phonebook_label_alt, data5, is_super_primary, data4, data3, data2, data1, data_set, contacts_status_updates.status AS contact_status, backup_id, preferred_phone_account_component_name, raw_contact_is_user_profile, status_updates.status_ts AS status_ts, data10, preferred_phone_account_id, data12, mimetype, status_updates.status_icon AS status_icon, data11, data14, data13, hash_id, data15 FROM view_data data LEFT OUTER JOIN agg_presence ON (contact_id = agg_presence.presence_contact_id) LEFT OUTER JOIN status_updates contacts_status_updates ON (status_update_id=contacts_status_updates.status_update_data_id) LEFT OUTER JOIN presence ON (presence_data_id=data._id) LEFT OUTER JOIN status_updates ON (status_updates.status_update_data_id=data._id) LEFT OUTER JOIN (SELECT 0 as STAT_DATA_ID,0 as x_times_used, 0 as x_last_time_used,0 as times_used, 0 as last_time_used where 0) as data_usage_stat ON (STAT_DATA_ID=data._id) WHERE (1 AND mimetype_id=5) AND (contact_id 2)
    at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:186)
    at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:142)
    at android.content.ContentProviderProxy.query(ContentProviderNative.java:472)
    at android.content.ContentResolver.query(ContentResolver.java:1183)
    at android.content.ContentResolver.query(ContentResolver.java:1115)
    at android.content.ContentResolver.query(ContentResolver.java:1071)
    at com.example.sosandvideo.MainActivity.onActivityResult(MainActivity.java:130)
    at android.app.Activity.dispatchActivityResult(Activity.java:8304)
    at android.app.ActivityThread.deliverResults(ActivityThread.java:5008)
        ... 11 more

Here are the relevant code that I have used:

package com.example.sosandvideo;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.nfc.Tag;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

;

import com.google.android.material.floatingactionbutton.FloatingActionButton;

import org.jetbrains.annotations.NotNull;

public class MainActivity extends AppCompatActivity {
    //    private Button add;
    private ImageView thumbnailTv;
    private TextView contactTv;
    private FloatingActionButton addFab;

    private static final int CONTACT_PERMISSION_CODE = 1;
    private static final int CONTACT_PICK_CODE = 2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        thumbnailTv = findViewById(R.id.thumbnailTv);
        contactTv = findViewById(R.id.contactTv);
        addFab = findViewById(R.id.addFab);
        addFab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //first we need to check contact permission
                if (checkContactPermission()) {

                    //if granted, pick a contact
                    pickContact();

                } else {
                    //not granted request for permission
                    requestContactPermission();
                }
            }
        });
    }

    private Boolean checkContactPermission() {
        //checking if the contact permission is granted or not
        boolean result = ContextCompat.checkSelfPermission(this,
                Manifest.permission.READ_CONTACTS) == (PackageManager.PERMISSION_GRANTED);
        return result;// true if granted or false
    }

    private void requestContactPermission() {
        //permission to request
        String[] permission = {Manifest.permission.READ_CONTACTS};
        ActivityCompat.requestPermissions(this, permission, CONTACT_PERMISSION_CODE);
    }

    private void pickContact() {
        //intent to pick contact
        Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
        startActivityForResult(intent, CONTACT_PICK_CODE);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull @NotNull String[] permissions, @NonNull @NotNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        // handle request for permission
        if (requestCode == CONTACT_PERMISSION_CODE) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                //permission granted now we can pick contacts
                pickContact();
            } else {
                //permission denied
                Toast.makeText(this, "Permission Denied", Toast.LENGTH_SHORT).show();
            }
        }

    }

    @SuppressLint("Range")
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable @org.jetbrains.annotations.Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        //handle intent results
        if (resultCode == RESULT_OK) {
            //calls when user pick a contact from the list
            if (requestCode == CONTACT_PICK_CODE) {
                Cursor cursor1;
                Cursor cursor2;
                //get data from intent
                Uri uri = data.getData();
                cursor1 = getContentResolver().query(uri, null, null, null, null);
                if (cursor1.moveToFirst()) {
                    //get contact date
                    String contactId = cursor1.getString(cursor1.getColumnIndex(ContactsContract.Contacts._ID));
                    String contactName = cursor1.getString(cursor1.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
                    String contactThumnail = cursor1.getString(cursor1.getColumnIndex(ContactsContract.Contacts.PHOTO_THUMBNAIL_URI));
                    String idResult = cursor1.getString(cursor1.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER));
                    int idResulthold = Integer.parseInt(idResult);
                    if (idResulthold == 1) {
                        cursor2 = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                                null,
                                ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " " + contactId,
                                null,
                                null);
                        while (cursor2.moveToNext()) {
                            String contactNum = cursor2.getString(cursor2.getColumnIndex
                                    (ContactsContract.CommonDataKinds.Phone.NUMBER));

                            contactTv.append("ID" + contactId);
                            contactTv.append("nName" + contactName);
                            contactTv.append("nNumber" + contactNum);
                            contactTv.append("nn");
                            if (contactThumnail != null) {
                                thumbnailTv.setImageURI(Uri.parse(contactThumnail));

                            } else {
                                thumbnailTv.setImageResource(R.drawable.ic_baseline_person_24);
                            }
                        }
                        cursor2.close();
                    }
                    cursor1.close();
                }


            }
        } else {
            //calls when user pressed back button or haven't selected any contacts
        }
    }
}

Here is the manifest code:

    <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.sosandvideo">
    <uses-permission android:name="android.permission.READ_CONTACTS"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.SOSandVideo">
        <activity android:name=".Home"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".MainActivity">
        </activity>
    </application>

</manifest>

How can I solve this ERROR

2

Answers


  1. Chosen as BEST ANSWER

    I changed my main activity file to this and changed how to fetch data using cursor As I said there is no work of SQL, Cursor generates SQL code automatically. i had a problem with fetching data from cursor movement.

       package com.example.sosandvideo;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.annotation.SuppressLint;
    import android.content.Intent;
    import android.database.Cursor;
    import android.net.Uri;
    import android.os.Bundle;
    import android.provider.ContactsContract;
    import android.view.View;
    import android.widget.Button;
    import android.widget.ListView;
    import android.widget.Toast;
    
    ;
    
    import com.example.sosandvideo.Contacts.Contact;
    import com.example.sosandvideo.Contacts.ContactAdapter;
    import com.example.sosandvideo.Contacts.DBhelper;
    
    import java.util.List;
    
    public class MainActivity extends AppCompatActivity {
        private static final int RESULT_PICK_CONTACT =1;
        ListView listview;
        List<Contact> list;
        ContactAdapter contactAdapter;
        private Button add;
        DBhelper db=new DBhelper();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate (savedInstanceState);
            setContentView (R.layout.activity_main);
    
    
           // phone = findViewById (R.id.contactTv);
            add = findViewById (R.id.addButton);
            listview=(ListView)findViewById(R.id.listView);
            list = db.getAllContacts();
            contactAdapter=new ContactAdapter(this,list);
            listview.setAdapter(contactAdapter);
    
            add.setOnClickListener (new View.OnClickListener () {
                @Override
                public void onClick(View v) {
                    Intent in = new Intent (Intent.ACTION_PICK, ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
                    startActivityForResult (in, RESULT_PICK_CONTACT);
                }
            });
    
        }
    
        @Override
        protected void onActivityResult(int requestCode, int resultCode,  Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (resultCode == RESULT_OK) {
                switch (requestCode) {
                    case RESULT_PICK_CONTACT:
                        contactPicked(data);
                        break;
                }
            } else {
                Toast.makeText(this, "Failed To pick contact", Toast.LENGTH_SHORT).show();
            }
        }
    
        @SuppressLint("Range")
        private void contactPicked(Intent data) {
            Cursor cursor = null;
    
            try {
                String phoneNo = null;
                int id;
                String name;
                Uri uri = data.getData ();
                cursor = getContentResolver ().query (uri, null, null,null,null);
                cursor.moveToFirst ();
                 id= cursor.getColumnIndex (ContactsContract.CommonDataKinds.Phone.CONTACT_ID);
    
                String phoneid= cursor.getString (id);
                String phoneNum= cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                name=cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                db.addContact(new Contact(phoneid,phoneNum,name));
                list = db.getAllContacts();
                contactAdapter.refresh(list);
    
            } catch (Exception e) {
                e.printStackTrace ();
            }
        }
    }
    

  2. shrinking down your error log to the relevant parts…
    SQLiteException: near "2": ... while compiling: SELECT ... contact_id 2

    your SQL should be SELECT ... contact_id=2

    In your source code you have this snipped that looks kind of wrong…
    ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " " + contactId,

    The way you are concating your sql statement you are prone to sql injection you should read more on that topic as well…

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search