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