Mon 21 Jul 22:43:21 CEST 2025
This commit is contained in:
		
							parent
							
								
									98b61b9555
								
							
						
					
					
						commit
						d4ddadba58
					
				| 
						 | 
				
			
			@ -0,0 +1,306 @@
 | 
			
		|||
/*
 | 
			
		||||
       Licensed to the Apache Software Foundation (ASF) under one
 | 
			
		||||
       or more contributor license agreements.  See the NOTICE file
 | 
			
		||||
       distributed with this work for additional information
 | 
			
		||||
       regarding copyright ownership.  The ASF licenses this file
 | 
			
		||||
       to you under the Apache License, Version 2.0 (the
 | 
			
		||||
       "License"); you may not use this file except in compliance
 | 
			
		||||
       with the License.  You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
         http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
       Unless required by applicable law or agreed to in writing,
 | 
			
		||||
       software distributed under the License is distributed on an
 | 
			
		||||
       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 | 
			
		||||
       KIND, either express or implied.  See the License for the
 | 
			
		||||
       specific language governing permissions and limitations
 | 
			
		||||
       under the License.
 | 
			
		||||
*/
 | 
			
		||||
package org.apache.cordova.contacts;
 | 
			
		||||
 | 
			
		||||
import org.apache.cordova.CallbackContext;
 | 
			
		||||
import org.apache.cordova.CordovaActivity;
 | 
			
		||||
import org.apache.cordova.CordovaPlugin;
 | 
			
		||||
import org.apache.cordova.PluginResult;
 | 
			
		||||
import org.json.JSONArray;
 | 
			
		||||
import org.json.JSONException;
 | 
			
		||||
import org.json.JSONObject;
 | 
			
		||||
 | 
			
		||||
import android.Manifest;
 | 
			
		||||
import android.app.Activity;
 | 
			
		||||
import android.content.Intent;
 | 
			
		||||
import android.content.pm.PackageManager;
 | 
			
		||||
import android.database.Cursor;
 | 
			
		||||
import android.os.Build;
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
import android.provider.ContactsContract.Contacts;
 | 
			
		||||
import android.provider.ContactsContract.RawContacts;
 | 
			
		||||
import android.util.Log;
 | 
			
		||||
 | 
			
		||||
import java.lang.reflect.Method;
 | 
			
		||||
 | 
			
		||||
public class ContactManager extends CordovaPlugin {
 | 
			
		||||
 | 
			
		||||
    private ContactAccessor contactAccessor;
 | 
			
		||||
    private CallbackContext callbackContext;        // The callback context from which we were invoked.
 | 
			
		||||
    private JSONArray executeArgs;
 | 
			
		||||
 | 
			
		||||
    private static final String LOG_TAG = "Contact Query";
 | 
			
		||||
 | 
			
		||||
    public static final int UNKNOWN_ERROR = 0;
 | 
			
		||||
    public static final int INVALID_ARGUMENT_ERROR = 1;
 | 
			
		||||
    public static final int TIMEOUT_ERROR = 2;
 | 
			
		||||
    public static final int PENDING_OPERATION_ERROR = 3;
 | 
			
		||||
    public static final int IO_ERROR = 4;
 | 
			
		||||
    public static final int NOT_SUPPORTED_ERROR = 5;
 | 
			
		||||
    public static final int OPERATION_CANCELLED_ERROR = 6;
 | 
			
		||||
    public static final int PERMISSION_DENIED_ERROR = 20;
 | 
			
		||||
    private static final int CONTACT_PICKER_RESULT = 1000;
 | 
			
		||||
    public static String [] permissions;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //Request code for the permissions picker (Pick is async and uses intents)
 | 
			
		||||
    public static final int SEARCH_REQ_CODE = 0;
 | 
			
		||||
    public static final int SAVE_REQ_CODE = 1;
 | 
			
		||||
    public static final int REMOVE_REQ_CODE = 2;
 | 
			
		||||
    public static final int PICK_REQ_CODE = 3;
 | 
			
		||||
 | 
			
		||||
    public static final String READ = Manifest.permission.READ_CONTACTS;
 | 
			
		||||
    public static final String WRITE = Manifest.permission.WRITE_CONTACTS;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructor.
 | 
			
		||||
     */
 | 
			
		||||
    public ContactManager() {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    protected void getReadPermission(int requestCode)
 | 
			
		||||
    {
 | 
			
		||||
        PermissionHelper.requestPermission(this, requestCode, READ);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    protected void getWritePermission(int requestCode)
 | 
			
		||||
    {
 | 
			
		||||
        PermissionHelper.requestPermission(this, requestCode, WRITE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Executes the request and returns PluginResult.
 | 
			
		||||
     *
 | 
			
		||||
     * @param action            The action to execute.
 | 
			
		||||
     * @param args              JSONArray of arguments for the plugin.
 | 
			
		||||
     * @param callbackContext   The callback context used when calling back into JavaScript.
 | 
			
		||||
     * @return                  True if the action was valid, false otherwise.
 | 
			
		||||
     */
 | 
			
		||||
    public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {
 | 
			
		||||
 | 
			
		||||
        this.callbackContext = callbackContext;
 | 
			
		||||
        this.executeArgs = args;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Check to see if we are on an Android 1.X device.  If we are return an error as we
 | 
			
		||||
         * do not support this as of Cordova 1.0.
 | 
			
		||||
         */
 | 
			
		||||
        if (android.os.Build.VERSION.RELEASE.startsWith("1.")) {
 | 
			
		||||
            callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, ContactManager.NOT_SUPPORTED_ERROR));
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Only create the contactAccessor after we check the Android version or the program will crash
 | 
			
		||||
         * older phones.
 | 
			
		||||
         */
 | 
			
		||||
        if (this.contactAccessor == null) {
 | 
			
		||||
            this.contactAccessor = new ContactAccessorSdk5(this.cordova);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (action.equals("search")) {
 | 
			
		||||
            if(PermissionHelper.hasPermission(this, READ)) {
 | 
			
		||||
                search(executeArgs);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                getReadPermission(SEARCH_REQ_CODE);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else if (action.equals("save")) {
 | 
			
		||||
            if(PermissionHelper.hasPermission(this, WRITE))
 | 
			
		||||
            {
 | 
			
		||||
                save(executeArgs);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                getWritePermission(SAVE_REQ_CODE);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else if (action.equals("remove")) {
 | 
			
		||||
            if(PermissionHelper.hasPermission(this, WRITE))
 | 
			
		||||
            {
 | 
			
		||||
                remove(executeArgs);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                getWritePermission(REMOVE_REQ_CODE);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else if (action.equals("pickContact")) {
 | 
			
		||||
            if(PermissionHelper.hasPermission(this, READ))
 | 
			
		||||
            {
 | 
			
		||||
                pickContactAsync();
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                getReadPermission(PICK_REQ_CODE);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void remove(JSONArray args) throws JSONException {
 | 
			
		||||
        final String contactId = args.getString(0);
 | 
			
		||||
        this.cordova.getThreadPool().execute(new Runnable() {
 | 
			
		||||
            public void run() {
 | 
			
		||||
                if (contactAccessor.remove(contactId)) {
 | 
			
		||||
                    callbackContext.success();
 | 
			
		||||
                } else {
 | 
			
		||||
                    callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, UNKNOWN_ERROR));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void save(JSONArray args) throws JSONException {
 | 
			
		||||
        final JSONObject contact = args.getJSONObject(0);
 | 
			
		||||
        this.cordova.getThreadPool().execute(new Runnable(){
 | 
			
		||||
            public void run() {
 | 
			
		||||
                JSONObject res = null;
 | 
			
		||||
                String id = contactAccessor.save(contact);
 | 
			
		||||
                if (id != null) {
 | 
			
		||||
                    try {
 | 
			
		||||
                        res = contactAccessor.getContactById(id);
 | 
			
		||||
                    } catch (JSONException e) {
 | 
			
		||||
                        Log.e(LOG_TAG, "JSON fail.", e);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                if (res != null) {
 | 
			
		||||
                    callbackContext.success(res);
 | 
			
		||||
                } else {
 | 
			
		||||
                    callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, UNKNOWN_ERROR));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void search(JSONArray args) throws JSONException
 | 
			
		||||
    {
 | 
			
		||||
        final JSONArray filter = args.getJSONArray(0);
 | 
			
		||||
        final JSONObject options = args.get(1) == null ? null : args.getJSONObject(1);
 | 
			
		||||
        this.cordova.getThreadPool().execute(new Runnable() {
 | 
			
		||||
            public void run() {
 | 
			
		||||
                JSONArray res = contactAccessor.search(filter, options);
 | 
			
		||||
                callbackContext.success(res);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Launches the Contact Picker to select a single contact.
 | 
			
		||||
     */
 | 
			
		||||
    private void pickContactAsync() {
 | 
			
		||||
        final CordovaPlugin plugin = (CordovaPlugin) this;
 | 
			
		||||
        Runnable worker = new Runnable() {
 | 
			
		||||
            public void run() {
 | 
			
		||||
                Intent contactPickerIntent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI);
 | 
			
		||||
                plugin.cordova.startActivityForResult(plugin, contactPickerIntent, CONTACT_PICKER_RESULT);
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
        this.cordova.getThreadPool().execute(worker);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called when user picks contact.
 | 
			
		||||
     * @param requestCode       The request code originally supplied to startActivityForResult(),
 | 
			
		||||
     *                          allowing you to identify who this result came from.
 | 
			
		||||
     * @param resultCode        The integer result code returned by the child activity through its setResult().
 | 
			
		||||
     * @param intent            An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
 | 
			
		||||
     * @throws JSONException
 | 
			
		||||
     */
 | 
			
		||||
    public void onActivityResult(int requestCode, int resultCode, final Intent intent) {
 | 
			
		||||
        if (requestCode == CONTACT_PICKER_RESULT) {
 | 
			
		||||
            if (resultCode == Activity.RESULT_OK) {
 | 
			
		||||
                String contactId = intent.getData().getLastPathSegment();
 | 
			
		||||
                // to populate contact data we require  Raw Contact ID
 | 
			
		||||
                // so we do look up for contact raw id first
 | 
			
		||||
                Cursor c =  this.cordova.getActivity().getContentResolver().query(RawContacts.CONTENT_URI,
 | 
			
		||||
                            new String[] {RawContacts._ID}, RawContacts.CONTACT_ID + " = " + contactId, null, null);
 | 
			
		||||
                if (!c.moveToFirst()) {
 | 
			
		||||
                    this.callbackContext.error("Error occured while retrieving contact raw id");
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                String id = c.getString(c.getColumnIndex(RawContacts._ID));
 | 
			
		||||
                c.close();
 | 
			
		||||
 | 
			
		||||
                try {
 | 
			
		||||
                    JSONObject contact = contactAccessor.getContactById(id);
 | 
			
		||||
                    this.callbackContext.success(contact);
 | 
			
		||||
                    return;
 | 
			
		||||
                } catch (JSONException e) {
 | 
			
		||||
                    Log.e(LOG_TAG, "JSON fail.", e);
 | 
			
		||||
                }
 | 
			
		||||
            } else if (resultCode == Activity.RESULT_CANCELED) {
 | 
			
		||||
                callbackContext.error(OPERATION_CANCELLED_ERROR);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, UNKNOWN_ERROR));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void onRequestPermissionResult(int requestCode, String[] permissions,
 | 
			
		||||
                                             int[] grantResults) throws JSONException
 | 
			
		||||
    {
 | 
			
		||||
        for(int r:grantResults)
 | 
			
		||||
        {
 | 
			
		||||
            if(r == PackageManager.PERMISSION_DENIED)
 | 
			
		||||
            {
 | 
			
		||||
                this.callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, PERMISSION_DENIED_ERROR));
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        switch(requestCode)
 | 
			
		||||
        {
 | 
			
		||||
            case SEARCH_REQ_CODE:
 | 
			
		||||
                search(executeArgs);
 | 
			
		||||
                break;
 | 
			
		||||
            case SAVE_REQ_CODE:
 | 
			
		||||
                save(executeArgs);
 | 
			
		||||
                break;
 | 
			
		||||
            case REMOVE_REQ_CODE:
 | 
			
		||||
                remove(executeArgs);
 | 
			
		||||
                break;
 | 
			
		||||
            case PICK_REQ_CODE:
 | 
			
		||||
                pickContactAsync();
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * This plugin launches an external Activity when a contact is picked, so we
 | 
			
		||||
     * need to implement the save/restore API in case the Activity gets killed
 | 
			
		||||
     * by the OS while it's in the background. We don't actually save anything
 | 
			
		||||
     * because picking a contact doesn't take in any arguments.
 | 
			
		||||
     */
 | 
			
		||||
    public void onRestoreStateForActivityResult(Bundle state, CallbackContext callbackContext) {
 | 
			
		||||
        this.callbackContext = callbackContext;
 | 
			
		||||
        this.contactAccessor = new ContactAccessorSdk5(this.cordova);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user