rhodes 2.0.0 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +6 -0
- data/Manifest.txt +3 -1
- data/bin/rhodes-setup +1 -32
- data/lib/framework/erb.rb +3 -3
- data/lib/framework/rhodes.rb +2 -2
- data/lib/framework/version.rb +2 -2
- data/lib/rhodes.rb +2 -2
- data/platform/android/Rhodes/AndroidManifest.xml +3 -2
- data/platform/android/Rhodes/jni/include/rhodes/jni/com_rhomobile_rhodes_Rhodes.h +2 -2
- data/platform/android/Rhodes/jni/src/rhodes.cpp +7 -5
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/Capabilities.java +2 -0
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/Rhodes.java +15 -6
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/camera/ImageCapture.java +5 -2
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/phonebook/Contact.java +8 -2
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/phonebook/ContactAccessor.java +11 -0
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/phonebook/ContactAccessorNew.java +310 -0
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/phonebook/ContactAccessorOld.java +275 -0
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/phonebook/Phonebook.java +125 -322
- data/platform/android/build/RhodesSRC_build.files +23 -21
- data/platform/android/build/android.rake +40 -17
- data/platform/iphone/Info.plist +1 -1
- data/platform/iphone/rbuild/iphone.rake +58 -33
- data/platform/iphone/rhorunner.xcodeproj/project.pbxproj +1 -1
- data/platform/shared/common/RhoPort.h +18 -3
- data/platform/shared/common/RhodesApp.cpp +76 -54
- data/platform/shared/common/StringConverter.h +3 -2
- data/platform/shared/common/stat.h +29 -4
- data/platform/shared/db/DBAdapter.cpp +2 -1
- data/platform/shared/db/DBAdapter.h +1 -1
- data/platform/shared/json/RJSONTokener.c +1 -1
- data/platform/shared/json/json_object.c +2 -2
- data/platform/shared/json/json_tokener.c +1 -1
- data/rhodes.gemspec +1 -1
- data/spec/phone_spec/app/Spec/contacts_spec.rb +10 -3
- data/spec/phone_spec/app/Spec/controller.rb +3 -3
- data/spec/phone_spec/app/Spec/mapview_spec.rb +3 -1
- data/spec/phone_spec/build.yml +2 -1
- metadata +6 -4
- data/rhobuild.yml +0 -39
data/CHANGELOG
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
## 2.0.1
|
2
|
+
* #4049590 - Android 2.2, rhodes rc2: take picture hangs
|
3
|
+
* #4103477 - Android 2.2: can't write to DB
|
4
|
+
* #3985537 - Android: cannot build with 2.2 sdk only
|
5
|
+
* #4038658 - Get free listening port on iphone
|
6
|
+
|
1
7
|
## 2.0.0
|
2
8
|
* #4053947 - Android: FindClass always return NULL when called outside of JNI_OnLoad
|
3
9
|
* #4060638 - reset functions don't wipe client_id
|
data/Manifest.txt
CHANGED
@@ -342,6 +342,9 @@ platform/android/Rhodes/src/com/rhomobile/rhodes/NavBar.java
|
|
342
342
|
platform/android/Rhodes/src/com/rhomobile/rhodes/NetworkConnectivityListener.java
|
343
343
|
platform/android/Rhodes/src/com/rhomobile/rhodes/NetworkStateTracker.java
|
344
344
|
platform/android/Rhodes/src/com/rhomobile/rhodes/phonebook/Contact.java
|
345
|
+
platform/android/Rhodes/src/com/rhomobile/rhodes/phonebook/ContactAccessor.java
|
346
|
+
platform/android/Rhodes/src/com/rhomobile/rhodes/phonebook/ContactAccessorNew.java
|
347
|
+
platform/android/Rhodes/src/com/rhomobile/rhodes/phonebook/ContactAccessorOld.java
|
345
348
|
platform/android/Rhodes/src/com/rhomobile/rhodes/phonebook/ContactField.java
|
346
349
|
platform/android/Rhodes/src/com/rhomobile/rhodes/phonebook/Phonebook.java
|
347
350
|
platform/android/Rhodes/src/com/rhomobile/rhodes/RhoConf.java
|
@@ -3550,7 +3553,6 @@ res/generators/templates/spec/app/mspec.rb
|
|
3550
3553
|
res/generators/templates/spec/app/spec_runner.rb
|
3551
3554
|
res/generators/templates/spec/app/SpecRunner/controller.rb
|
3552
3555
|
res/generators/templates/spec/app/SpecRunner/index.erb
|
3553
|
-
rhobuild.yml
|
3554
3556
|
rhobuild.yml.example
|
3555
3557
|
rhodes.gemspec
|
3556
3558
|
spec/framework_spec/app/Account/account.rb
|
data/bin/rhodes-setup
CHANGED
@@ -55,38 +55,7 @@ if ENV['ANDROID_HOME']
|
|
55
55
|
android = ENV['ANDROID_HOME']
|
56
56
|
end
|
57
57
|
|
58
|
-
|
59
|
-
android = prompt_for("Android SDK path", android, false)
|
60
|
-
break if android.nil?
|
61
|
-
|
62
|
-
android = android.gsub(/\\/,"/")
|
63
|
-
apilevel = -1
|
64
|
-
android_platform_dir = "/platforms/android-1.5"
|
65
|
-
Dir.glob(File.join(android, 'platforms', '*')).each do |dir|
|
66
|
-
props = File.join(dir, 'source.properties')
|
67
|
-
next unless File.file? props
|
68
|
-
File.open(props, 'r') do |f|
|
69
|
-
while line = f.gets
|
70
|
-
next if line !~ /^\s*AndroidVersion\.ApiLevel\s*=\s*([0-9]+)\s*$/
|
71
|
-
apilevel = $1.to_i
|
72
|
-
break
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
if apilevel == 3
|
77
|
-
android_platform_dir = dir[android.length..-1]
|
78
|
-
break
|
79
|
-
end
|
80
|
-
end
|
81
|
-
android = "" if apilevel == -1
|
82
|
-
|
83
|
-
unless File.directory? File.join(android, android_platform_dir)
|
84
|
-
puts "Invalid Android SDK path"
|
85
|
-
next
|
86
|
-
end
|
87
|
-
|
88
|
-
break
|
89
|
-
end
|
58
|
+
android = prompt_for("Android SDK path", android, false)
|
90
59
|
|
91
60
|
# try to detect android ndk
|
92
61
|
ndk = ""
|
data/lib/framework/erb.rb
CHANGED
@@ -750,11 +750,11 @@ class ERB
|
|
750
750
|
# setup of an ERB _compiler_ object.
|
751
751
|
#
|
752
752
|
def set_eoutvar(compiler, eoutvar = '_erbout')
|
753
|
-
compiler.put_cmd = "#{eoutvar}.concat"
|
754
|
-
compiler.insert_cmd = "#{eoutvar}.concat"
|
753
|
+
compiler.put_cmd = "#{eoutvar}.force_encoding('utf-8');#{eoutvar}.concat"
|
754
|
+
compiler.insert_cmd = "#{eoutvar}.force_encoding('utf-8');#{eoutvar}.concat"
|
755
755
|
|
756
756
|
cmd = []
|
757
|
-
cmd.push "#{eoutvar} = ''"
|
757
|
+
cmd.push "#{eoutvar} = '';#{eoutvar}.force_encoding('utf-8')"
|
758
758
|
|
759
759
|
compiler.pre_cmd = cmd
|
760
760
|
|
data/lib/framework/rhodes.rb
CHANGED
data/lib/framework/version.rb
CHANGED
data/lib/rhodes.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
<?xml version="1.0" encoding="utf-8"?>
|
2
2
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
3
3
|
package="com.rhomobile.rhodes"
|
4
|
-
android:versionCode="
|
5
|
-
android:versionName="2.0.
|
4
|
+
android:versionCode="22"
|
5
|
+
android:versionName="2.0.2">
|
6
6
|
<uses-sdk android:minSdkVersion="3" />
|
7
7
|
<application android:icon="@drawable/icon"
|
8
8
|
android:multiprocess="true"
|
@@ -35,4 +35,5 @@
|
|
35
35
|
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
|
36
36
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
37
37
|
<uses-permission android:name="android.permission.VIBRATE" />
|
38
|
+
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
|
38
39
|
</manifest>
|
@@ -16,10 +16,10 @@ extern "C" {
|
|
16
16
|
/*
|
17
17
|
* Class: com_rhomobile_rhodes_Rhodes
|
18
18
|
* Method: createRhodesApp
|
19
|
-
* Signature: (Ljava/lang/String;)V
|
19
|
+
* Signature: (Ljava/lang/String;Ljava/lang/String;)V
|
20
20
|
*/
|
21
21
|
JNIEXPORT void JNICALL Java_com_rhomobile_rhodes_Rhodes_createRhodesApp
|
22
|
-
(JNIEnv *, jobject, jstring);
|
22
|
+
(JNIEnv *, jobject, jstring, jstring);
|
23
23
|
|
24
24
|
/*
|
25
25
|
* Class: com_rhomobile_rhodes_Rhodes
|
@@ -20,7 +20,8 @@ const char *rho_java_class[] = {
|
|
20
20
|
#undef RHODES_DEFINE_JAVA_CLASS
|
21
21
|
};
|
22
22
|
|
23
|
-
static
|
23
|
+
static std::string g_root_path;
|
24
|
+
static std::string g_sqlite_journals_path;
|
24
25
|
|
25
26
|
static pthread_key_t g_thrkey;
|
26
27
|
|
@@ -179,7 +180,7 @@ jmethodID getJNIClassStaticMethod(JNIEnv *env, jclass cls, const char *name, con
|
|
179
180
|
|
180
181
|
const char* rho_native_rhopath()
|
181
182
|
{
|
182
|
-
return
|
183
|
+
return g_root_path.c_str();
|
183
184
|
}
|
184
185
|
|
185
186
|
jint JNI_OnLoad(JavaVM* vm, void* /*reserved*/)
|
@@ -328,14 +329,15 @@ RHO_GLOBAL void JNICALL Java_com_rhomobile_rhodes_Rhodes_initClassLoader
|
|
328
329
|
}
|
329
330
|
|
330
331
|
RHO_GLOBAL void JNICALL Java_com_rhomobile_rhodes_Rhodes_createRhodesApp
|
331
|
-
(JNIEnv *env, jobject, jstring
|
332
|
+
(JNIEnv *env, jobject, jstring root_path, jstring sqlite_journals_path)
|
332
333
|
{
|
333
334
|
if (!set_capabilities(env)) return;
|
334
335
|
|
335
|
-
|
336
|
+
g_root_path = rho_cast<std::string>(root_path);
|
337
|
+
g_sqlite_journals_path = rho_cast<std::string>(sqlite_journals_path);
|
336
338
|
|
337
339
|
// Init SQLite temp directory
|
338
|
-
sqlite3_temp_directory = (char*)
|
340
|
+
sqlite3_temp_directory = (char*)g_sqlite_journals_path.c_str();
|
339
341
|
|
340
342
|
const char* szRootPath = rho_native_rhopath();
|
341
343
|
|
@@ -2,11 +2,13 @@ package com.rhomobile.rhodes;
|
|
2
2
|
|
3
3
|
public class Capabilities {
|
4
4
|
|
5
|
+
public static boolean AUDIO_ENABLED = true;
|
5
6
|
public static boolean CAMERA_ENABLED = true;
|
6
7
|
public static boolean GPS_ENABLED = true;
|
7
8
|
public static boolean NETWORK_STATE_ENABLED = true;
|
8
9
|
public static boolean PHONE_ENABLED = true;
|
9
10
|
public static boolean PIM_ENABLED = true;
|
11
|
+
public static boolean RECORD_AUDIO_ENABLED = true;
|
10
12
|
public static boolean VIBRATE_ENABLED = true;
|
11
13
|
|
12
14
|
}
|
@@ -120,7 +120,7 @@ public class Rhodes extends Activity {
|
|
120
120
|
|
121
121
|
private String rootPath = null;
|
122
122
|
|
123
|
-
public native void createRhodesApp(String
|
123
|
+
public native void createRhodesApp(String rootPath, String sqliteJournalsPath);
|
124
124
|
public native void startRhodesApp();
|
125
125
|
public native void stopRhodesApp();
|
126
126
|
|
@@ -155,17 +155,26 @@ public class Rhodes extends Activity {
|
|
155
155
|
return rootPath;
|
156
156
|
}
|
157
157
|
|
158
|
-
private
|
158
|
+
private ApplicationInfo getAppInfo() {
|
159
159
|
String pkgName = getPackageName();
|
160
160
|
try {
|
161
161
|
ApplicationInfo info = getPackageManager().getApplicationInfo(pkgName, 0);
|
162
|
-
|
163
|
-
return path;
|
162
|
+
return info;
|
164
163
|
} catch (NameNotFoundException e) {
|
165
164
|
throw new RuntimeException("Internal error: package " + pkgName + " not found: " + e.getMessage());
|
166
165
|
}
|
167
166
|
}
|
168
167
|
|
168
|
+
private String getSqliteJournalsPath() {
|
169
|
+
String path = getAppInfo().dataDir + "/sqlite_stmt_journals/";
|
170
|
+
new File(path).mkdirs();
|
171
|
+
return path;
|
172
|
+
}
|
173
|
+
|
174
|
+
private String phoneMemoryRootPath() {
|
175
|
+
return getAppInfo().dataDir + "/rhodata/";
|
176
|
+
}
|
177
|
+
|
169
178
|
private String sdcardRootPath() {
|
170
179
|
String sdPath = Environment.getExternalStorageDirectory().getAbsolutePath();
|
171
180
|
String pkgName = getPackageName();
|
@@ -174,7 +183,7 @@ public class Rhodes extends Activity {
|
|
174
183
|
}
|
175
184
|
|
176
185
|
public static String getBlobPath() {
|
177
|
-
return RhodesInstance.getInstance().getRootPath() + "db/db-files";
|
186
|
+
return RhodesInstance.getInstance().getRootPath() + "/db/db-files";
|
178
187
|
}
|
179
188
|
|
180
189
|
private RhoLogConf m_rhoLogConf = new RhoLogConf();
|
@@ -491,7 +500,7 @@ public class Rhodes extends Activity {
|
|
491
500
|
finish();
|
492
501
|
return;
|
493
502
|
}
|
494
|
-
createRhodesApp(getRootPath());
|
503
|
+
createRhodesApp(getRootPath(), getSqliteJournalsPath());
|
495
504
|
|
496
505
|
boolean fullScreen = true;
|
497
506
|
if (RhoConf.isExist("full_screen"))
|
@@ -41,6 +41,7 @@ import android.view.SurfaceHolder;
|
|
41
41
|
import android.view.SurfaceView;
|
42
42
|
import android.view.View;
|
43
43
|
import android.view.Window;
|
44
|
+
import android.view.WindowManager;
|
44
45
|
import android.view.View.OnClickListener;
|
45
46
|
import android.widget.ImageButton;
|
46
47
|
|
@@ -64,7 +65,7 @@ public class ImageCapture extends Activity implements SurfaceHolder.Callback, On
|
|
64
65
|
super.onCreate(icicle);
|
65
66
|
Logger.D(TAG, "onCreate");
|
66
67
|
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
67
|
-
getWindow().setFlags(
|
68
|
+
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
68
69
|
getWindow().setFormat(PixelFormat.TRANSLUCENT);
|
69
70
|
setContentView(AndroidR.layout.camera);
|
70
71
|
|
@@ -137,7 +138,9 @@ public class ImageCapture extends Activity implements SurfaceHolder.Callback, On
|
|
137
138
|
camera.stopPreview();
|
138
139
|
}
|
139
140
|
Camera.Parameters p = camera.getParameters();
|
140
|
-
|
141
|
+
int newW = (w >> 3) << 3;
|
142
|
+
int newH = (h >> 3) << 3;
|
143
|
+
p.setPreviewSize(newW, newH);
|
141
144
|
camera.setParameters(p);
|
142
145
|
camera.setPreviewDisplay(holder);
|
143
146
|
camera.startPreview();
|
@@ -26,6 +26,7 @@ import java.util.Map;
|
|
26
26
|
|
27
27
|
public class Contact {
|
28
28
|
|
29
|
+
private String id = null;
|
29
30
|
private Map<String, ContactField> fields = new HashMap<String, ContactField>();
|
30
31
|
private Iterator<ContactField> iter = null;
|
31
32
|
|
@@ -43,11 +44,16 @@ public class Contact {
|
|
43
44
|
if ( fields.containsKey(key) )
|
44
45
|
return fields.get(key).getValue();
|
45
46
|
|
46
|
-
return
|
47
|
+
return null;
|
48
|
+
}
|
49
|
+
|
50
|
+
public void setId(String v) {
|
51
|
+
id = v;
|
52
|
+
setField(Phonebook.PB_ID, "{" + v + "}");
|
47
53
|
}
|
48
54
|
|
49
55
|
public String id() {
|
50
|
-
return
|
56
|
+
return id;
|
51
57
|
}
|
52
58
|
|
53
59
|
public void moveToBegin() {
|
@@ -0,0 +1,11 @@
|
|
1
|
+
package com.rhomobile.rhodes.phonebook;
|
2
|
+
|
3
|
+
import java.util.Map;
|
4
|
+
|
5
|
+
public interface ContactAccessor {
|
6
|
+
|
7
|
+
public Map<String, Contact> getAll() throws Exception;
|
8
|
+
public void save(Contact contact) throws Exception;
|
9
|
+
public void remove(Contact contact);
|
10
|
+
|
11
|
+
}
|
@@ -0,0 +1,310 @@
|
|
1
|
+
package com.rhomobile.rhodes.phonebook;
|
2
|
+
|
3
|
+
import java.util.HashMap;
|
4
|
+
import java.util.Map;
|
5
|
+
|
6
|
+
import com.rhomobile.rhodes.Rhodes;
|
7
|
+
import com.rhomobile.rhodes.RhodesInstance;
|
8
|
+
|
9
|
+
import android.accounts.Account;
|
10
|
+
import android.accounts.AccountManager;
|
11
|
+
import android.content.ContentResolver;
|
12
|
+
import android.content.ContentUris;
|
13
|
+
import android.content.ContentValues;
|
14
|
+
import android.database.Cursor;
|
15
|
+
import android.net.Uri;
|
16
|
+
import android.provider.ContactsContract.CommonDataKinds.Email;
|
17
|
+
import android.provider.ContactsContract.CommonDataKinds.Organization;
|
18
|
+
import android.provider.ContactsContract.CommonDataKinds.Phone;
|
19
|
+
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
|
20
|
+
import android.provider.ContactsContract.Data;
|
21
|
+
import android.provider.ContactsContract.RawContacts;
|
22
|
+
|
23
|
+
public class ContactAccessorNew implements ContactAccessor {
|
24
|
+
|
25
|
+
//private static final String TAG = "ContactsAccessorNew";
|
26
|
+
|
27
|
+
private static final String PB_ID = Phonebook.PB_ID;
|
28
|
+
private static final String PB_FIRST_NAME = Phonebook.PB_FIRST_NAME;
|
29
|
+
private static final String PB_LAST_NAME = Phonebook.PB_LAST_NAME;
|
30
|
+
private static final String PB_MOBILE_NUMBER = Phonebook.PB_MOBILE_NUMBER;
|
31
|
+
private static final String PB_HOME_NUMBER = Phonebook.PB_HOME_NUMBER;
|
32
|
+
private static final String PB_BUSINESS_NUMBER = Phonebook.PB_BUSINESS_NUMBER;
|
33
|
+
private static final String PB_EMAIL_ADDRESS = Phonebook.PB_EMAIL_ADDRESS;
|
34
|
+
private static final String PB_COMPANY_NAME = Phonebook.PB_COMPANY_NAME;
|
35
|
+
|
36
|
+
private ContentResolver cr;
|
37
|
+
private String accName;
|
38
|
+
private String accType;
|
39
|
+
|
40
|
+
public ContactAccessorNew() throws Exception {
|
41
|
+
Rhodes r = RhodesInstance.getInstance();
|
42
|
+
|
43
|
+
Account[] accounts = AccountManager.get(r).getAccounts();
|
44
|
+
if (accounts.length == 0) {
|
45
|
+
accName = "rhodes@rhomobile.com";
|
46
|
+
accType = "com.rhomobile";
|
47
|
+
}
|
48
|
+
else {
|
49
|
+
Account acnt = accounts[0];
|
50
|
+
accName = acnt.name;
|
51
|
+
accType = acnt.type;
|
52
|
+
}
|
53
|
+
|
54
|
+
cr = r.getContentResolver();
|
55
|
+
}
|
56
|
+
|
57
|
+
private void fillName(String id, Contact contact) {
|
58
|
+
contact.setField(PB_FIRST_NAME, "");
|
59
|
+
contact.setField(PB_LAST_NAME, "");
|
60
|
+
|
61
|
+
Cursor cursor = cr.query(Data.CONTENT_URI,
|
62
|
+
new String[] {StructuredName.DISPLAY_NAME},
|
63
|
+
Data.RAW_CONTACT_ID + "=? AND " + Data.MIMETYPE + "=?",
|
64
|
+
new String[] {id, StructuredName.CONTENT_ITEM_TYPE},
|
65
|
+
null);
|
66
|
+
try {
|
67
|
+
if (!cursor.moveToFirst())
|
68
|
+
return;
|
69
|
+
|
70
|
+
String name = cursor.getString(cursor.getColumnIndex(StructuredName.DISPLAY_NAME));
|
71
|
+
if (name != null) {
|
72
|
+
String[] names = name.split(" ");
|
73
|
+
if (names.length == 1) {
|
74
|
+
contact.setField(PB_FIRST_NAME, name);
|
75
|
+
}
|
76
|
+
else {
|
77
|
+
contact.setField(PB_FIRST_NAME, names[0]);
|
78
|
+
contact.setField(PB_LAST_NAME, names[1]);
|
79
|
+
}
|
80
|
+
}
|
81
|
+
}
|
82
|
+
finally {
|
83
|
+
cursor.close();
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
private void fillPhones(String id, Contact contact) {
|
88
|
+
Cursor cursor = cr.query(Data.CONTENT_URI,
|
89
|
+
new String[] {Phone.NUMBER, Phone.TYPE},
|
90
|
+
Data.RAW_CONTACT_ID + "=? AND " + Data.MIMETYPE + "=?",
|
91
|
+
new String[] {id, Phone.CONTENT_ITEM_TYPE},
|
92
|
+
null);
|
93
|
+
try {
|
94
|
+
if (!cursor.moveToFirst())
|
95
|
+
return;
|
96
|
+
|
97
|
+
int numColumn = cursor.getColumnIndex(Phone.NUMBER);
|
98
|
+
int typeColumn = cursor.getColumnIndex(Phone.TYPE);
|
99
|
+
do {
|
100
|
+
switch (cursor.getInt(typeColumn)) {
|
101
|
+
case Phone.TYPE_HOME:
|
102
|
+
contact.setField(PB_HOME_NUMBER, cursor.getString(numColumn));
|
103
|
+
break;
|
104
|
+
case Phone.TYPE_WORK:
|
105
|
+
contact.setField(PB_BUSINESS_NUMBER, cursor.getString(numColumn));
|
106
|
+
break;
|
107
|
+
case Phone.TYPE_MOBILE:
|
108
|
+
contact.setField(PB_MOBILE_NUMBER, cursor.getString(numColumn));
|
109
|
+
break;
|
110
|
+
}
|
111
|
+
} while (cursor.moveToNext());
|
112
|
+
}
|
113
|
+
finally {
|
114
|
+
cursor.close();
|
115
|
+
}
|
116
|
+
}
|
117
|
+
|
118
|
+
private void fillEmails(String id, Contact contact) {
|
119
|
+
Cursor cursor = cr.query(Data.CONTENT_URI,
|
120
|
+
new String[] {Email.DATA},
|
121
|
+
Data.RAW_CONTACT_ID + "=? AND " + Data.MIMETYPE + "=?",
|
122
|
+
new String[] {id, Email.CONTENT_ITEM_TYPE},
|
123
|
+
null);
|
124
|
+
try {
|
125
|
+
if (!cursor.moveToFirst())
|
126
|
+
return;
|
127
|
+
|
128
|
+
String data = cursor.getString(cursor.getColumnIndex(Email.DATA));
|
129
|
+
contact.setField(PB_EMAIL_ADDRESS, data);
|
130
|
+
}
|
131
|
+
finally {
|
132
|
+
cursor.close();
|
133
|
+
}
|
134
|
+
}
|
135
|
+
|
136
|
+
private void fillCompany(String id, Contact contact) {
|
137
|
+
Cursor cursor = cr.query(Data.CONTENT_URI,
|
138
|
+
new String[] {Organization.COMPANY},
|
139
|
+
Data.RAW_CONTACT_ID + "=? AND " + Data.MIMETYPE + "=?",
|
140
|
+
new String[] {id, Organization.CONTENT_ITEM_TYPE},
|
141
|
+
null);
|
142
|
+
try {
|
143
|
+
if (!cursor.moveToFirst())
|
144
|
+
return;
|
145
|
+
String company = cursor.getString(cursor.getColumnIndex(Organization.COMPANY));
|
146
|
+
contact.setField(PB_COMPANY_NAME, company);
|
147
|
+
}
|
148
|
+
finally {
|
149
|
+
cursor.close();
|
150
|
+
}
|
151
|
+
}
|
152
|
+
|
153
|
+
public Map<String, Contact> getAll() throws Exception {
|
154
|
+
Map<String, Contact> contacts = new HashMap<String, Contact>();
|
155
|
+
|
156
|
+
Cursor cursor = cr.query(RawContacts.CONTENT_URI,
|
157
|
+
new String[] {RawContacts._ID},
|
158
|
+
RawContacts.DELETED + "=0", null, null);
|
159
|
+
try {
|
160
|
+
if (!cursor.moveToFirst())
|
161
|
+
return contacts;
|
162
|
+
|
163
|
+
do {
|
164
|
+
Contact contact = new Contact();
|
165
|
+
|
166
|
+
String id = cursor.getString(cursor.getColumnIndex(RawContacts._ID));
|
167
|
+
contact.setId(id);
|
168
|
+
|
169
|
+
fillName(id, contact);
|
170
|
+
fillPhones(id, contact);
|
171
|
+
fillEmails(id, contact);
|
172
|
+
fillCompany(id, contact);
|
173
|
+
|
174
|
+
contacts.put(contact.getField(PB_ID), contact);
|
175
|
+
} while (cursor.moveToNext());
|
176
|
+
}
|
177
|
+
finally {
|
178
|
+
cursor.close();
|
179
|
+
}
|
180
|
+
|
181
|
+
return contacts;
|
182
|
+
}
|
183
|
+
|
184
|
+
private void create(Contact contact) throws Exception {
|
185
|
+
String id = contact.id();
|
186
|
+
|
187
|
+
if (id == null || id.length() == 0) {
|
188
|
+
ContentValues values = new ContentValues();
|
189
|
+
values.put(RawContacts.ACCOUNT_NAME, accName);
|
190
|
+
values.put(RawContacts.ACCOUNT_TYPE, accType);
|
191
|
+
values.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED);
|
192
|
+
Uri uri = cr.insert(RawContacts.CONTENT_URI, values);
|
193
|
+
id = String.valueOf(ContentUris.parseId(uri));
|
194
|
+
contact.setId(id);
|
195
|
+
}
|
196
|
+
}
|
197
|
+
|
198
|
+
private void saveData(Contact contact, ContentValues values, String where, String[] whereValues) throws Exception {
|
199
|
+
String id = contact.id();
|
200
|
+
values.put(Data.RAW_CONTACT_ID, Long.parseLong(id));
|
201
|
+
|
202
|
+
// Search is there is already record with the same raw_contact_id and mimetype
|
203
|
+
long dataId = 0;
|
204
|
+
|
205
|
+
StringBuilder w = new StringBuilder();
|
206
|
+
w.append(Data.RAW_CONTACT_ID + "=? AND " + Data.MIMETYPE + "=?");
|
207
|
+
if (where != null)
|
208
|
+
w.append(" AND " + where);
|
209
|
+
where = w.toString();
|
210
|
+
|
211
|
+
String mimetype = (String)values.get(Data.MIMETYPE);
|
212
|
+
int wvSize = 2;
|
213
|
+
if (whereValues != null)
|
214
|
+
wvSize += whereValues.length;
|
215
|
+
String[] wv = new String[wvSize];
|
216
|
+
wv[0] = id;
|
217
|
+
wv[1] = mimetype;
|
218
|
+
if (whereValues != null)
|
219
|
+
System.arraycopy(whereValues, 0, wv, 2, whereValues.length);
|
220
|
+
|
221
|
+
Cursor cursor = cr.query(Data.CONTENT_URI, new String[] {Data._ID}, where, wv, null);
|
222
|
+
try {
|
223
|
+
if (cursor.moveToFirst())
|
224
|
+
dataId = cursor.getLong(cursor.getColumnIndex(Data._ID));
|
225
|
+
}
|
226
|
+
finally {
|
227
|
+
cursor.close();
|
228
|
+
}
|
229
|
+
|
230
|
+
// Do update if found, insert otherwise
|
231
|
+
if (dataId != 0)
|
232
|
+
cr.update(Data.CONTENT_URI, values,
|
233
|
+
Data._ID + "=?", new String[] {String.valueOf(dataId)});
|
234
|
+
else
|
235
|
+
cr.insert(Data.CONTENT_URI, values);
|
236
|
+
}
|
237
|
+
|
238
|
+
private void saveData(Contact contact, ContentValues values) throws Exception {
|
239
|
+
saveData(contact, values, null, null);
|
240
|
+
}
|
241
|
+
|
242
|
+
private void updateName(Contact contact) throws Exception {
|
243
|
+
String firstName = contact.getField(PB_FIRST_NAME);
|
244
|
+
String lastName = contact.getField(PB_LAST_NAME);
|
245
|
+
|
246
|
+
ContentValues values = new ContentValues();
|
247
|
+
values.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
|
248
|
+
values.put(StructuredName.DISPLAY_NAME, firstName + " " + lastName);
|
249
|
+
values.put(StructuredName.GIVEN_NAME, firstName);
|
250
|
+
values.put(StructuredName.FAMILY_NAME, lastName);
|
251
|
+
saveData(contact, values);
|
252
|
+
}
|
253
|
+
|
254
|
+
private void updatePhones(Contact contact) throws Exception {
|
255
|
+
String[] phones = {PB_MOBILE_NUMBER, PB_HOME_NUMBER, PB_BUSINESS_NUMBER};
|
256
|
+
int[] types = {Phone.TYPE_MOBILE, Phone.TYPE_HOME, Phone.TYPE_WORK};
|
257
|
+
|
258
|
+
for (int i = 0; i < phones.length; ++i) {
|
259
|
+
String phName = phones[i];
|
260
|
+
String value = contact.getField(phName);
|
261
|
+
if (value == null || value.length() == 0)
|
262
|
+
continue;
|
263
|
+
|
264
|
+
ContentValues values = new ContentValues();
|
265
|
+
values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
|
266
|
+
values.put(Phone.NUMBER, value);
|
267
|
+
values.put(Phone.TYPE, types[i]);
|
268
|
+
saveData(contact, values, Phone.TYPE + "=?", new String[] {String.valueOf(types[i])});
|
269
|
+
}
|
270
|
+
}
|
271
|
+
|
272
|
+
private void updateEmails(Contact contact) throws Exception {
|
273
|
+
String value = contact.getField(PB_EMAIL_ADDRESS);
|
274
|
+
if (value == null || value.length() == 0)
|
275
|
+
return;
|
276
|
+
|
277
|
+
ContentValues values = new ContentValues();
|
278
|
+
values.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
|
279
|
+
values.put(Email.DATA, value);
|
280
|
+
saveData(contact, values);
|
281
|
+
}
|
282
|
+
|
283
|
+
private void updateCompany(Contact contact) throws Exception {
|
284
|
+
String value = contact.getField(PB_COMPANY_NAME);
|
285
|
+
if (value == null || value.length() == 0)
|
286
|
+
return;
|
287
|
+
|
288
|
+
ContentValues values = new ContentValues();
|
289
|
+
values.put(Data.MIMETYPE, Organization.CONTENT_ITEM_TYPE);
|
290
|
+
values.put(Organization.COMPANY, value);
|
291
|
+
saveData(contact, values);
|
292
|
+
}
|
293
|
+
|
294
|
+
public void save(Contact contact) throws Exception {
|
295
|
+
create(contact);
|
296
|
+
|
297
|
+
updateName(contact);
|
298
|
+
updatePhones(contact);
|
299
|
+
updateEmails(contact);
|
300
|
+
updateCompany(contact);
|
301
|
+
}
|
302
|
+
|
303
|
+
public void remove(Contact contact) {
|
304
|
+
String id = contact.id();
|
305
|
+
if (id == null || id.length() == 0)
|
306
|
+
return;
|
307
|
+
cr.delete(RawContacts.CONTENT_URI, RawContacts._ID + "=?", new String[] {id});
|
308
|
+
}
|
309
|
+
|
310
|
+
}
|