NTP-38623 | Dialer app (#1104)
Co-authored-by: Varnit Goyal <varnit.goyal@navi.com> Co-authored-by: Ashish Deo <ashish.deo@navi.com> Co-authored-by: Mantri Ramkishor <mantri.ramkishor@navi.com>
This commit is contained in:
@@ -114,7 +114,7 @@ def enableHermes = project.ext.react.get("enableHermes", false);
|
||||
|
||||
|
||||
def VERSION_CODE = 237
|
||||
def VERSION_NAME = "2.17.4"
|
||||
def VERSION_NAME = "2.18.0"
|
||||
|
||||
android {
|
||||
namespace "com.avapp"
|
||||
@@ -223,10 +223,12 @@ dependencies {
|
||||
implementation 'androidx.core:core-splashscreen:1.0.1'
|
||||
implementation 'com.navi.android:pulse:1.0.1-cosmos'
|
||||
implementation 'androidx.work:work-runtime-ktx:2.8.1'
|
||||
implementation "androidx.room:room-runtime:2.5.0"
|
||||
annotationProcessor "androidx.room:room-compiler:2.5.0"
|
||||
|
||||
//noinspection GradleDynamicVersion
|
||||
implementation("com.facebook.react:react-android")
|
||||
|
||||
|
||||
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}")
|
||||
debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
|
||||
exclude group:'com.squareup.okhttp3', module:'okhttp'
|
||||
|
||||
3
android/app/proguard-rules.pro
vendored
3
android/app/proguard-rules.pro
vendored
@@ -16,4 +16,5 @@
|
||||
-keep class com.navi.alfred.db.** { *; }
|
||||
-keep class com.navi.alfred.AlfredConfig { *; }
|
||||
-keepattributes SourceFile,LineNumberTable # Keep file names and line numbers.
|
||||
-keep public class * extends java.lang.Exception # Optional: Keep custom exceptions.
|
||||
-keep public class * extends java.lang.Exception # Optional: Keep custom exceptions.
|
||||
-keep class com.avapp.contentProvider.ackNumbers.AckNumberContentProvider { *; }
|
||||
@@ -1,6 +1,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.avapp">
|
||||
package="com.avapp"
|
||||
>
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
@@ -39,6 +40,7 @@
|
||||
<queries>
|
||||
<package android:name="com.whatsapp" />
|
||||
<package android:name="com.whatsapp.w4b" />
|
||||
<package android:name="com.avapp" />
|
||||
</queries>
|
||||
<uses-permission android:name="android.permission.USE_EXACT_ALARM"/>
|
||||
<application
|
||||
@@ -64,8 +66,21 @@
|
||||
/>
|
||||
<service android:name="com.supersami.foregroundservice.ForegroundService" android:foregroundServiceType="location"></service>
|
||||
<service android:name="com.supersami.foregroundservice.ForegroundServiceTask" android:foregroundServiceType="location"></service>
|
||||
|
||||
<provider
|
||||
<provider
|
||||
android:name="com.avapp.contentProvider.ackNumbers.AckNumberContentProvider"
|
||||
android:authorities="com.avapp.ackProvider"
|
||||
android:exported="true"
|
||||
android:grantUriPermissions="true"
|
||||
android:enabled="true">
|
||||
</provider>
|
||||
<provider
|
||||
android:name="com.avapp.contentProvider.primaryNumber.PrimaryNumberContentProvider"
|
||||
android:authorities="com.avapp.primaryNumberProvider"
|
||||
android:exported="true"
|
||||
android:grantUriPermissions="true"
|
||||
android:enabled="true">
|
||||
</provider>
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.provider"
|
||||
android:exported="false"
|
||||
@@ -73,7 +88,9 @@
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_paths" />
|
||||
</provider>
|
||||
</provider>
|
||||
|
||||
|
||||
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
|
||||
@@ -15,6 +15,7 @@ import androidx.annotation.Nullable;
|
||||
import androidx.core.content.FileProvider;
|
||||
|
||||
import com.facebook.react.bridge.ActivityEventListener;
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.BaseActivityEventListener;
|
||||
import com.facebook.react.bridge.Promise;
|
||||
import com.facebook.react.bridge.Callback;
|
||||
@@ -22,6 +23,8 @@ import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.WritableArray;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.uimanager.UIManagerModule;
|
||||
import com.navi.alfred.AlfredManager;
|
||||
import com.navi.pulse.PulseManager;
|
||||
@@ -53,7 +56,7 @@ public class DeviceUtilsModule extends ReactContextBaseJavaModule {
|
||||
|
||||
private int WHATSAPP_SHARE_REQUEST_CODE = 12345;
|
||||
|
||||
public DeviceUtilsModule(@Nullable ReactApplicationContext reactContext){
|
||||
public DeviceUtilsModule(@Nullable ReactApplicationContext reactContext) {
|
||||
super(reactContext);
|
||||
RNContext = reactContext;
|
||||
reactContext.addActivityEventListener(mActivityEventListener);
|
||||
@@ -67,10 +70,10 @@ public class DeviceUtilsModule extends ReactContextBaseJavaModule {
|
||||
private final ActivityEventListener mActivityEventListener = new BaseActivityEventListener() {
|
||||
@Override
|
||||
public void onActivityResult(Activity activity, int i, int i1, @Nullable Intent intent) {
|
||||
if(i1 != RESULT_CANCELED) {
|
||||
if (i == WHATSAPP_SHARE_REQUEST_CODE && (imageFile!=null)) {
|
||||
new File(Uri.fromFile(imageFile).getPath()).delete();
|
||||
}
|
||||
if (i1 != RESULT_CANCELED) {
|
||||
if (i == WHATSAPP_SHARE_REQUEST_CODE && (imageFile != null)) {
|
||||
new File(Uri.fromFile(imageFile).getPath()).delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -306,7 +309,7 @@ public class DeviceUtilsModule extends ReactContextBaseJavaModule {
|
||||
}
|
||||
|
||||
public Intent getWhatsappShareIntent(String message, String imageUrl, String mimeType, String packageName,
|
||||
String format, String fileName) {
|
||||
String format, String fileName) {
|
||||
Intent sendIntent = new Intent();
|
||||
sendIntent.setAction(Intent.ACTION_SEND);
|
||||
sendIntent.putExtra(Intent.EXTRA_TEXT, message);
|
||||
@@ -332,7 +335,7 @@ public class DeviceUtilsModule extends ReactContextBaseJavaModule {
|
||||
|
||||
@ReactMethod
|
||||
public void sendContentToWhatsapp(String message, String fileUri, String mimeType, String format, String fileName,
|
||||
Promise promise) {
|
||||
Promise promise) {
|
||||
try {
|
||||
ArrayList<String> appsInstalled = isWhatsAppInstalled();
|
||||
int numberOfAppsInstalled = appsInstalled.size();
|
||||
@@ -378,5 +381,60 @@ public class DeviceUtilsModule extends ReactContextBaseJavaModule {
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void isAppInstalled(String packageName, Promise promise) {
|
||||
PackageManager pm = RNContext.getPackageManager();
|
||||
try {
|
||||
ApplicationInfo info = pm.getApplicationInfo(packageName, 0);
|
||||
if (info != null) {
|
||||
promise.resolve(true); // App is installed
|
||||
} else {
|
||||
promise.resolve(false); // App is not installed
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
promise.resolve(false); // App is not installed
|
||||
} catch (Exception e) {
|
||||
promise.reject("ERROR", "An unexpected error occurred: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void getAppInfo(String packageName, Promise promise) {
|
||||
PackageManager pm = RNContext.getPackageManager();
|
||||
try {
|
||||
// Get PackageInfo for the given package name
|
||||
PackageInfo packageInfo = pm.getPackageInfo(packageName, 0);
|
||||
|
||||
// Create a WritableMap to store the app information
|
||||
WritableMap map = Arguments.createMap();
|
||||
map.putInt("version", packageInfo.versionCode); // App version name
|
||||
map.putString("versionName", packageInfo.versionName); // App version code (deprecated in API 28+ but still useful for older devices)
|
||||
|
||||
promise.resolve(map); // Resolve the promise with the app info map
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
promise.resolve(false); // App not found, resolve with false
|
||||
} catch (Exception e) {
|
||||
promise.reject("ERROR", "An unexpected error occurred: " + e.getMessage()); // Handle unexpected errors
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void getAppInfoFromFilePath(String apkFilePath, Promise promise) {
|
||||
try {
|
||||
PackageManager pm = RNContext.getPackageManager();
|
||||
PackageInfo packageInfo = pm.getPackageArchiveInfo(apkFilePath, 0);
|
||||
|
||||
if (packageInfo != null) {
|
||||
WritableMap map = Arguments.createMap();
|
||||
map.putString("packageName", packageInfo.packageName);
|
||||
map.putInt("version", packageInfo.versionCode);
|
||||
map.putString("versionName", packageInfo.versionName);
|
||||
promise.resolve(map);
|
||||
} else {
|
||||
promise.reject("APK_ERROR", "Failed to read APK file.");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
promise.reject(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,9 +11,12 @@ import android.app.Application;
|
||||
import android.content.Context;
|
||||
|
||||
import com.avapp.appInstallerModule.ApkInstallerPackage;
|
||||
import com.avapp.contentProvider.ContentProviderPackage;
|
||||
import com.avapp.callModule.CallModulePackage;
|
||||
import com.avapp.deviceDataSync.DeviceDataSyncPackage;
|
||||
import com.avapp.photoModule.PhotoModulePackage;
|
||||
import com.avapp.phoneStateBroadcastReceiver.PhoneStateModulePackage;
|
||||
import com.avapp.sharedPreference.SharedPreferencesPackage;
|
||||
import com.avapp.utils.FirebaseRemoteConfigHelper;
|
||||
import com.avapp.wifiDetailsModule.WifiDetailsModulePackage;
|
||||
import com.avapp.restartApp.RestartPackage;
|
||||
@@ -69,6 +72,9 @@ public class MainApplication extends Application implements ReactApplication, Ap
|
||||
packages.add(new WifiDetailsModulePackage());
|
||||
packages.add(new ApkInstallerPackage());
|
||||
packages.add(new RestartPackage());
|
||||
packages.add(new CallModulePackage());
|
||||
packages.add(new SharedPreferencesPackage());
|
||||
packages.add(new ContentProviderPackage());
|
||||
return packages;
|
||||
}
|
||||
|
||||
@@ -280,4 +286,4 @@ public class MainApplication extends Application implements ReactApplication, Ap
|
||||
public void onActivityDestroyed(@NonNull Activity activity) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
226
android/app/src/main/java/com/avapp/callModule/CallModule.java
Normal file
226
android/app/src/main/java/com/avapp/callModule/CallModule.java
Normal file
@@ -0,0 +1,226 @@
|
||||
package com.avapp.callModule;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.bridge.Callback;
|
||||
import android.os.Build;
|
||||
import androidx.core.content.FileProvider;
|
||||
import com.avapp.BuildConfig;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import com.facebook.react.bridge.Callback;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import com.facebook.react.bridge.Promise;
|
||||
|
||||
public class CallModule extends ReactContextBaseJavaModule {
|
||||
|
||||
private final ReactApplicationContext reactContext;
|
||||
private static final String TAG = "CallModule";
|
||||
private static final String CALLING_APP_PACKAGE = "org.fossify.phone";
|
||||
|
||||
private String pendingRecipient;
|
||||
private String pendingExotelNumber;
|
||||
private BroadcastReceiver installReceiver;
|
||||
|
||||
public CallModule(ReactApplicationContext reactContext) {
|
||||
super(reactContext);
|
||||
this.reactContext = reactContext;
|
||||
registerInstallReceiver();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return "CallModule";
|
||||
}
|
||||
|
||||
private void registerInstallReceiver() {
|
||||
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
|
||||
filter.addDataScheme("package");
|
||||
|
||||
installReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
Uri data = intent.getData();
|
||||
Log.d(TAG, "InstallReceiver: onReceive: " + intent.getAction());
|
||||
if (data != null) {
|
||||
String installedPackage = data.getSchemeSpecificPart();
|
||||
if (CALLING_APP_PACKAGE.equals(installedPackage)) {
|
||||
Log.d(TAG, "Installed package detected: " + installedPackage);
|
||||
retryCallAfterInstall();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
reactContext.registerReceiver(installReceiver, filter);
|
||||
}
|
||||
|
||||
private void retryCallAfterInstall() {
|
||||
Activity activity = getCurrentActivity();
|
||||
if (activity != null && pendingRecipient != null) {
|
||||
makeCall(activity, pendingRecipient, pendingExotelNumber);
|
||||
} else if (pendingRecipient != null) {
|
||||
Intent intent = new Intent(Intent.ACTION_CALL);
|
||||
intent.setData(Uri.parse("tel:" + pendingRecipient));
|
||||
intent.putExtra("cosmos_call_numb", pendingRecipient);
|
||||
intent.putExtra("cosmos_call_numb_exotel", pendingExotelNumber);
|
||||
intent.setPackage(CALLING_APP_PACKAGE);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // REQUIRED!
|
||||
activity.startActivity(intent);
|
||||
}
|
||||
|
||||
// Reset stored values
|
||||
pendingRecipient = null;
|
||||
pendingExotelNumber = null;
|
||||
}
|
||||
|
||||
|
||||
public static String maskFirstSixDigits(String number) {
|
||||
if (number == null || number.length() != 10) {
|
||||
Log.e("AVAPP", "number incorrect");
|
||||
}
|
||||
if (number.length() == 10) {
|
||||
return "******" + number.substring(6);
|
||||
}else {
|
||||
return "******" + number.substring(8); // Mask first 6 digits
|
||||
|
||||
}}
|
||||
|
||||
private boolean isAppInstalled(Activity activity, String packageName) {
|
||||
try {
|
||||
activity.getPackageManager().getPackageInfo(packageName, 0);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void isDialerAppValidApkFile(String filePath, Promise promise) {
|
||||
try {
|
||||
boolean isValid = isValidApkFile(filePath);
|
||||
promise.resolve(isValid);
|
||||
} catch (Exception e) {
|
||||
Log.e("ApkInstaller", "Error validating APK file", e);
|
||||
promise.reject("APK_VALIDATION_ERROR", e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isValidApkFile(String filePath) {
|
||||
try {
|
||||
File apkFile = new File(filePath);
|
||||
if (!apkFile.exists() || apkFile.length() == 0) {
|
||||
return false;
|
||||
}
|
||||
try (ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(apkFile))) {
|
||||
ZipEntry zipEntry = zipInputStream.getNextEntry();
|
||||
return zipEntry != null;
|
||||
} catch (Exception e) {
|
||||
Log.e("ApkInstaller", "Invalid APK file", e);
|
||||
return false;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e("ApkInstaller", "Error installing APK", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void launchCallIntent(String recipient, String exotelNumber, String filePath, Callback callback) {
|
||||
Activity activity = getCurrentActivity();
|
||||
if (activity == null) {
|
||||
Log.e(TAG, "Activity is null, cannot make call");
|
||||
return;
|
||||
}
|
||||
|
||||
// Mask the recipient number for logging
|
||||
String maskedNumber = maskFirstSixDigits(recipient);
|
||||
Log.d(TAG, "Attempting to call: " + maskedNumber + " using " + CALLING_APP_PACKAGE);
|
||||
pendingRecipient = recipient;
|
||||
pendingExotelNumber = exotelNumber;
|
||||
if (!isAppInstalled(activity, CALLING_APP_PACKAGE)) {
|
||||
Log.d(TAG, "App not installed, installing it...");
|
||||
installApk(filePath, callback);
|
||||
return;
|
||||
}
|
||||
|
||||
// Make the call if the app is installed
|
||||
makeCall(activity, recipient, exotelNumber);
|
||||
}
|
||||
|
||||
private void makeCall(Activity activity, String recipient, String exotelNumber) {
|
||||
Intent intent = new Intent(Intent.ACTION_CALL);
|
||||
intent.setData(Uri.parse("tel:" + pendingRecipient));
|
||||
intent.putExtra("cosmos_call_numb", pendingRecipient);
|
||||
intent.putExtra("cosmos_call_numb_exotel", pendingExotelNumber);
|
||||
intent.setPackage(CALLING_APP_PACKAGE);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // Ensure the specific app is used
|
||||
|
||||
if (intent.resolveActivity(activity.getPackageManager()) != null) {
|
||||
activity.startActivity(intent);
|
||||
Log.d(TAG, "Call initiated successfully.");
|
||||
} else {
|
||||
Log.e(TAG, "No app found to handle the call.");
|
||||
}
|
||||
}
|
||||
|
||||
private void promptForInstall(Uri apkUri) {
|
||||
try {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
}
|
||||
reactContext.startActivity(intent);
|
||||
} catch (Exception e) {
|
||||
Log.e("ApkInstaller", "promptForInstall: Error installing APK", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void installApk(String filePath, Callback callback) {
|
||||
try {
|
||||
File apkFile = new File(filePath);
|
||||
if (!isValidApkFile(filePath)) {
|
||||
callback.invoke("Invalid or corrupted apk file", null);
|
||||
return;
|
||||
}
|
||||
|
||||
Uri apkUri;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
apkUri = FileProvider.getUriForFile(reactContext, BuildConfig.APPLICATION_ID + ".provider", apkFile);
|
||||
} else {
|
||||
apkUri = Uri.fromFile(apkFile);
|
||||
}
|
||||
promptForInstall(apkUri);
|
||||
callback.invoke(null, "Success");
|
||||
} catch (Exception e) {
|
||||
Log.e("ApkInstaller", "Error installing APK", e);
|
||||
callback.invoke(e.toString(), null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCatalystInstanceDestroy() {
|
||||
if (installReceiver != null) {
|
||||
reactContext.unregisterReceiver(installReceiver);
|
||||
installReceiver = null;
|
||||
}
|
||||
super.onCatalystInstanceDestroy();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.avapp.callModule;
|
||||
|
||||
import com.facebook.react.uimanager.ViewManager;
|
||||
|
||||
import com.facebook.react.ReactPackage;
|
||||
import com.facebook.react.bridge.NativeModule;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class CallModulePackage implements ReactPackage {
|
||||
@Override
|
||||
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NativeModule> createNativeModules(
|
||||
ReactApplicationContext reactContext) {
|
||||
List<NativeModule> modules = new ArrayList<>();
|
||||
|
||||
modules.add(new CallModule(reactContext));
|
||||
|
||||
return modules;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
package com.avapp.contentProvider;
|
||||
|
||||
import com.avapp.contentProvider.ackNumbers.AckNumbersEntity;
|
||||
import com.avapp.contentProvider.primaryNumber.PrimaryNumberEntity;
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.Promise;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.bridge.WritableArray;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
|
||||
public class ContentProviderModule extends ReactContextBaseJavaModule {
|
||||
|
||||
private ReactApplicationContext reactApplicationContext;
|
||||
private CosmosDatabase database;
|
||||
private final ExecutorService executorService = Executors.newSingleThreadExecutor();
|
||||
|
||||
|
||||
public ContentProviderModule(ReactApplicationContext reactContext) {
|
||||
super(reactContext);
|
||||
this.reactApplicationContext = reactContext;
|
||||
database = CosmosDatabase.getInstance(reactApplicationContext);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "ContentProviderModule";
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void getAckNumbers(Promise promise) {
|
||||
ContentProviderThreadPool.getExecutorService().execute(() -> {
|
||||
try {
|
||||
|
||||
List<AckNumbersEntity> ackNumbers = database.ackNumberDataDao().getAllData();
|
||||
WritableArray writableArray = Arguments.createArray();
|
||||
for (AckNumbersEntity entity : ackNumbers) {
|
||||
WritableMap map = Arguments.createMap();
|
||||
map.putString("fromNumber", entity.fromNumber);
|
||||
map.putString("toNumber", entity.toNumber);
|
||||
map.putString("created_at", entity.createdAt+"");
|
||||
map.putInt("id", entity.id);
|
||||
writableArray.pushMap(map);
|
||||
}
|
||||
promise.resolve(writableArray);
|
||||
} catch (Exception e) {
|
||||
promise.reject(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void deleteAckNumberById(Integer id, Promise promise) {
|
||||
ContentProviderThreadPool.getExecutorService().execute(() -> {
|
||||
try {
|
||||
database.ackNumberDataDao().deleteDataById(id);
|
||||
promise.resolve(true);
|
||||
} catch (Exception e) {
|
||||
promise.reject(e);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void addPhoneNumber(String phoneNumber, Promise promise) {
|
||||
ContentProviderThreadPool.getExecutorService().execute(()->{
|
||||
try {
|
||||
//check if entry already exist
|
||||
PrimaryNumberEntity primaryNumberExist = database.primaryNumberDataDao().getDataByPhone(phoneNumber);
|
||||
if(primaryNumberExist !=null) {
|
||||
promise.resolve(phoneNumber);
|
||||
return;
|
||||
}
|
||||
PrimaryNumberEntity primaryNumber = new PrimaryNumberEntity();
|
||||
primaryNumber.phoneNumber = phoneNumber;
|
||||
database.primaryNumberDataDao().insert(primaryNumber);
|
||||
promise.resolve(phoneNumber);
|
||||
}
|
||||
catch (Exception e) {
|
||||
promise.resolve(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void deletePhoneNumber(String phoneNumber, Promise promise) {
|
||||
ContentProviderThreadPool.getExecutorService().execute(()->{
|
||||
try {
|
||||
database.primaryNumberDataDao().deleteDataByPhone(phoneNumber);
|
||||
promise.resolve(phoneNumber);
|
||||
}
|
||||
|
||||
catch (Exception e) {
|
||||
promise.reject(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void bulkAddPhoneNumbers(ReadableArray phoneNumbers, Promise promise) {
|
||||
executorService.execute(() -> {
|
||||
try {
|
||||
for (int i = 0; i < phoneNumbers.size(); i++) {
|
||||
String phoneNumber = phoneNumbers.getString(i);
|
||||
PrimaryNumberEntity primaryNumberExist = database.primaryNumberDataDao().getDataByPhone(phoneNumber);
|
||||
if(primaryNumberExist !=null) {
|
||||
promise.resolve(phoneNumber);
|
||||
return;
|
||||
}
|
||||
PrimaryNumberEntity primaryNumber = new PrimaryNumberEntity();
|
||||
primaryNumber.phoneNumber = phoneNumber;
|
||||
database.primaryNumberDataDao().insert(primaryNumber);
|
||||
}
|
||||
promise.resolve(true);
|
||||
} catch (Exception e) {
|
||||
promise.reject(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void bulkDeletePhoneNumbers(ReadableArray phoneNumbers, Promise promise) {
|
||||
executorService.execute(() -> {
|
||||
try {
|
||||
for (int i = 0; i < phoneNumbers.size(); i++) {
|
||||
String phoneNumber = phoneNumbers.getString(i);
|
||||
database.primaryNumberDataDao().deleteDataByPhone(phoneNumber);
|
||||
}
|
||||
promise.resolve(true);
|
||||
} catch (Exception e) {
|
||||
promise.reject(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void cleanTables(Promise promise) {
|
||||
ContentProviderThreadPool.getExecutorService().execute(()->{
|
||||
try {
|
||||
database.primaryNumberDataDao().deleteAllRows();
|
||||
database.ackNumberDataDao().deleteAllRows();
|
||||
promise.resolve("done");
|
||||
}
|
||||
|
||||
catch (Exception e) {
|
||||
promise.reject(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ReactMethod
|
||||
public void getTableLength(Promise promise) {
|
||||
ContentProviderThreadPool.getExecutorService().execute(()->{
|
||||
try {
|
||||
|
||||
promise.resolve(database.primaryNumberDataDao().getTableLength());
|
||||
}
|
||||
|
||||
catch (Exception e) {
|
||||
promise.reject(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.avapp.contentProvider;
|
||||
|
||||
import com.facebook.react.ReactPackage;
|
||||
import com.facebook.react.bridge.NativeModule;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.uimanager.ViewManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class ContentProviderPackage implements ReactPackage {
|
||||
@Override
|
||||
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NativeModule> createNativeModules(
|
||||
ReactApplicationContext reactContext) {
|
||||
List<NativeModule> modules = new ArrayList<>();
|
||||
|
||||
modules.add(new ContentProviderModule(reactContext));
|
||||
|
||||
return modules;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.avapp.contentProvider;
|
||||
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class ContentProviderThreadPool {
|
||||
|
||||
private static final int CORE_POOL_SIZE = 10;
|
||||
private static final int MAX_POOL_SIZE = 20;
|
||||
private static final long KEEP_ALIVE_TIME = 30L;
|
||||
private static final TimeUnit TIME_UNIT = TimeUnit.SECONDS;
|
||||
|
||||
private static final BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>();
|
||||
|
||||
private static final ExecutorService executorService = new ThreadPoolExecutor(
|
||||
CORE_POOL_SIZE,
|
||||
MAX_POOL_SIZE,
|
||||
KEEP_ALIVE_TIME,
|
||||
TIME_UNIT,
|
||||
workQueue
|
||||
);
|
||||
|
||||
public static ExecutorService getExecutorService() {
|
||||
return executorService;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.avapp.contentProvider;
|
||||
|
||||
import androidx.room.Database;
|
||||
import androidx.room.Room;
|
||||
import androidx.room.RoomDatabase;
|
||||
import android.content.Context;
|
||||
|
||||
import com.avapp.contentProvider.ackNumbers.AckNumberDataDao;
|
||||
import com.avapp.contentProvider.ackNumbers.AckNumbersEntity;
|
||||
import com.avapp.contentProvider.primaryNumber.PrimaryNumberDataDao;
|
||||
import com.avapp.contentProvider.primaryNumber.PrimaryNumberEntity;
|
||||
|
||||
@Database(entities = {AckNumbersEntity.class, PrimaryNumberEntity.class}, version = 1)
|
||||
public abstract class CosmosDatabase extends RoomDatabase {
|
||||
public abstract AckNumberDataDao ackNumberDataDao();
|
||||
public abstract PrimaryNumberDataDao primaryNumberDataDao();
|
||||
|
||||
|
||||
private static volatile CosmosDatabase INSTANCE;
|
||||
|
||||
public static CosmosDatabase getInstance(Context context) {
|
||||
if (INSTANCE == null) {
|
||||
synchronized (CosmosDatabase.class) {
|
||||
if (INSTANCE == null) {
|
||||
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
|
||||
CosmosDatabase.class, "cosmos")
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
package com.avapp.contentProvider.ackNumbers;
|
||||
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentValues;
|
||||
import android.content.UriMatcher;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
|
||||
import com.avapp.contentProvider.CosmosDatabase;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
public class AckNumberContentProvider extends ContentProvider {
|
||||
|
||||
private static final int DATA = 100;
|
||||
private static final int DATA_ID = 101;
|
||||
|
||||
private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
|
||||
|
||||
static {
|
||||
sUriMatcher.addURI(AckNumberContractProvider.AUTHORITY, AckNumberContractProvider.PATH_DATA, DATA);
|
||||
sUriMatcher.addURI(AckNumberContractProvider.AUTHORITY, AckNumberContractProvider.PATH_DATA + "/#", DATA_ID);
|
||||
}
|
||||
|
||||
private CosmosDatabase database;
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
Log.d("ack number provider", "");
|
||||
database = CosmosDatabase.getInstance(getContext());
|
||||
|
||||
if (database == null) {
|
||||
Log.e("AckNumber", "Failed to initialise database");
|
||||
return false; // Return false if the database could not be initialised
|
||||
}
|
||||
|
||||
Log.d("AckNumber", "Content Provider created and database initialised");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
|
||||
int match = sUriMatcher.match(uri);
|
||||
Cursor cursor;
|
||||
|
||||
switch (match) {
|
||||
case DATA:
|
||||
cursor = database.ackNumberDataDao().getAllDataCursor();
|
||||
break;
|
||||
case DATA_ID:
|
||||
int id = Integer.parseInt(uri.getLastPathSegment());
|
||||
cursor = database.ackNumberDataDao().getDataByIdCursor(id);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown URI: " + uri);
|
||||
}
|
||||
|
||||
cursor.setNotificationUri(getContext().getContentResolver(), uri);
|
||||
return cursor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri insert(Uri uri, ContentValues values) {
|
||||
Log.d("in insert","");
|
||||
int match = sUriMatcher.match(uri);
|
||||
if (match == DATA) {
|
||||
AckNumbersEntity data = new AckNumbersEntity();
|
||||
data.fromNumber = values.getAsString("fromPhoneNumber");
|
||||
data.toNumber = values.getAsString("toPhoneNumber");
|
||||
data.createdAt= System.currentTimeMillis();
|
||||
|
||||
long id = database.ackNumberDataDao().insert(data);
|
||||
if (id == -1) {
|
||||
throw new IllegalArgumentException("Failed to insert row into " + uri);
|
||||
}
|
||||
|
||||
getContext().getContentResolver().notifyChange(uri, null);
|
||||
return Uri.withAppendedPath(uri, String.valueOf(id));
|
||||
} else {
|
||||
throw new IllegalArgumentException("Insertion not supported for " + uri);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int delete(Uri uri, String selection, String[] selectionArgs) {
|
||||
int match = sUriMatcher.match(uri);
|
||||
if (match == DATA_ID) {
|
||||
int id = Integer.parseInt(uri.getLastPathSegment());
|
||||
AckNumbersEntity data = database.ackNumberDataDao().getDataById(id);
|
||||
if (data != null) {
|
||||
return database.ackNumberDataDao().delete(data);
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Deletion not supported for " + uri);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
||||
int match = sUriMatcher.match(uri);
|
||||
if (match == DATA_ID) {
|
||||
int id = Integer.parseInt(uri.getLastPathSegment());
|
||||
AckNumbersEntity data = database.ackNumberDataDao().getDataById(id);
|
||||
if (data != null) {
|
||||
data.toNumber = values.getAsString("toPhoneNumber");
|
||||
data.fromNumber = values.getAsString("fromPhoneNumber");
|
||||
data.createdAt= System.currentTimeMillis();
|
||||
return database.ackNumberDataDao().update(data);
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Update not supported for " + uri);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType(Uri uri) {
|
||||
int match = sUriMatcher.match(uri);
|
||||
switch (match) {
|
||||
case DATA:
|
||||
return "vnd.android.cursor.dir/" + AckNumberContractProvider.AUTHORITY + "." + AckNumberContractProvider.PATH_DATA;
|
||||
case DATA_ID:
|
||||
return "vnd.android.cursor.item/" + AckNumberContractProvider.AUTHORITY + "." + AckNumberContractProvider.PATH_DATA;
|
||||
default:
|
||||
throw new IllegalStateException("Unknown URI: " + uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.avapp.contentProvider.ackNumbers;
|
||||
|
||||
|
||||
import android.net.Uri;
|
||||
import android.provider.BaseColumns;
|
||||
|
||||
public final class AckNumberContractProvider {
|
||||
//com.avapp.ack.provider
|
||||
public static final String AUTHORITY = "com.avapp.ackProvider";
|
||||
public static final Uri BASE_CONTENT_URI = Uri.parse("content://" + AUTHORITY);
|
||||
|
||||
public static final String PATH_DATA = "data";
|
||||
|
||||
public static final class DataEntry implements BaseColumns {
|
||||
public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, PATH_DATA);
|
||||
|
||||
public static final String TABLE_NAME = "cosmos";
|
||||
public static final String COLUMN_NAME_FROM_NUMBER = "fromNumber";
|
||||
public static final String COLUMN_NAME_TO_NUMBER = "toNumber";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.avapp.contentProvider.ackNumbers;
|
||||
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Insert;
|
||||
import androidx.room.Query;
|
||||
import androidx.room.Update;
|
||||
import androidx.room.Delete;
|
||||
|
||||
import android.database.Cursor;
|
||||
|
||||
import com.avapp.contentProvider.primaryNumber.PrimaryNumberEntity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Dao
|
||||
public interface AckNumberDataDao {
|
||||
@Insert
|
||||
long insert(AckNumbersEntity data);
|
||||
|
||||
@Query("SELECT * FROM ack")
|
||||
List<AckNumbersEntity> getAllData();
|
||||
|
||||
|
||||
@Query("SELECT * FROM ack WHERE id = :id")
|
||||
AckNumbersEntity getDataById(int id);
|
||||
|
||||
@Query("DELETE FROM ack WHERE id = :id")
|
||||
int deleteDataById(int id);
|
||||
|
||||
@Query("SELECT * FROM ack WHERE fromNumber= :fromPhone")
|
||||
AckNumbersEntity getDataByFromPhone(String fromPhone);
|
||||
|
||||
@Query("SELECT * FROM ack WHERE toNumber= :toPhone")
|
||||
AckNumbersEntity getDataByToPhone(String toPhone);
|
||||
|
||||
@Query("DELETE FROM ack")
|
||||
void deleteAllRows();
|
||||
|
||||
@Update
|
||||
int update(AckNumbersEntity data);
|
||||
|
||||
@Delete
|
||||
int delete(AckNumbersEntity data);
|
||||
|
||||
// Custom methods to return Cursor for Content Provider
|
||||
@Query("SELECT * FROM ack")
|
||||
Cursor getAllDataCursor();
|
||||
|
||||
@Query("SELECT * FROM ack WHERE id = :id")
|
||||
Cursor getDataByIdCursor(int id);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.avapp.contentProvider.ackNumbers;
|
||||
|
||||
import androidx.room.ColumnInfo;
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.PrimaryKey;
|
||||
|
||||
@Entity(tableName = "ack")
|
||||
public class AckNumbersEntity {
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
public int id;
|
||||
|
||||
@ColumnInfo(name = "created_at")
|
||||
public long createdAt;
|
||||
|
||||
public String fromNumber;
|
||||
public String toNumber;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package com.avapp.contentProvider.primaryNumber;
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentValues;
|
||||
import android.content.UriMatcher;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.avapp.contentProvider.CosmosDatabase;
|
||||
|
||||
public class PrimaryNumberContentProvider extends ContentProvider {
|
||||
|
||||
private static final int DATA = 100;
|
||||
private static final int DATA_ID = 101;
|
||||
|
||||
private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
|
||||
|
||||
static {
|
||||
sUriMatcher.addURI(PrimaryNumberContractProvider.AUTHORITY, PrimaryNumberContractProvider.PATH_DATA, DATA);
|
||||
sUriMatcher.addURI(PrimaryNumberContractProvider.AUTHORITY, PrimaryNumberContractProvider.PATH_DATA + "/#", DATA_ID);
|
||||
}
|
||||
|
||||
private CosmosDatabase database;
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
database = CosmosDatabase.getInstance(getContext());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
|
||||
int match = sUriMatcher.match(uri);
|
||||
Cursor cursor;
|
||||
|
||||
switch (match) {
|
||||
case DATA:
|
||||
cursor = database.primaryNumberDataDao().getAllDataCursor();
|
||||
break;
|
||||
case DATA_ID:
|
||||
String id = uri.getLastPathSegment();
|
||||
cursor = database.primaryNumberDataDao().getDataByPhoneCursor(id);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown URI: " + uri);
|
||||
}
|
||||
|
||||
cursor.setNotificationUri(getContext().getContentResolver(), uri);
|
||||
return cursor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri insert(Uri uri, ContentValues values) {
|
||||
int match = sUriMatcher.match(uri);
|
||||
if (match == DATA) {
|
||||
PrimaryNumberEntity data = new PrimaryNumberEntity();
|
||||
data.phoneNumber = values.getAsString("phoneNumber");
|
||||
|
||||
long id = database.primaryNumberDataDao().insert(data);
|
||||
if (id == -1) {
|
||||
throw new IllegalArgumentException("Failed to insert row into " + uri);
|
||||
}
|
||||
|
||||
getContext().getContentResolver().notifyChange(uri, null);
|
||||
return Uri.withAppendedPath(uri, String.valueOf(id));
|
||||
} else {
|
||||
throw new IllegalArgumentException("Insertion not supported for " + uri);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int delete(Uri uri, String selection, String[] selectionArgs) {
|
||||
int match = sUriMatcher.match(uri);
|
||||
if (match == DATA_ID) {
|
||||
int id = Integer.parseInt(uri.getLastPathSegment());
|
||||
PrimaryNumberEntity data = database.primaryNumberDataDao().getDataById(id);
|
||||
if (data != null) {
|
||||
return database.primaryNumberDataDao().delete(data);
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Deletion not supported for " + uri);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
||||
int match = sUriMatcher.match(uri);
|
||||
if (match == DATA_ID) {
|
||||
int id = Integer.parseInt(uri.getLastPathSegment());
|
||||
PrimaryNumberEntity data = database.primaryNumberDataDao().getDataById(id);
|
||||
if (data != null) {
|
||||
data.phoneNumber = values.getAsString("phoneNumber");
|
||||
return database.primaryNumberDataDao().update(data);
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Update not supported for " + uri);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType(Uri uri) {
|
||||
int match = sUriMatcher.match(uri);
|
||||
switch (match) {
|
||||
case DATA:
|
||||
return "vnd.android.cursor.dir/" + PrimaryNumberContractProvider.AUTHORITY + "." + PrimaryNumberContractProvider.PATH_DATA;
|
||||
case DATA_ID:
|
||||
return "vnd.android.cursor.item/" + PrimaryNumberContractProvider.AUTHORITY + "." + PrimaryNumberContractProvider.PATH_DATA;
|
||||
default:
|
||||
throw new IllegalStateException("Unknown URI: " + uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.avapp.contentProvider.primaryNumber;
|
||||
import android.net.Uri;
|
||||
import android.provider.BaseColumns;
|
||||
|
||||
|
||||
public final class PrimaryNumberContractProvider {
|
||||
public static final String AUTHORITY = "com.avapp.primaryNumberProvider";//"com.cosmos.myapp.provider";
|
||||
public static final Uri BASE_CONTENT_URI = Uri.parse("content://" + AUTHORITY);
|
||||
|
||||
public static final String PATH_DATA = "data";
|
||||
|
||||
public static final class DataEntry implements BaseColumns {
|
||||
public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, PATH_DATA);
|
||||
|
||||
public static final String TABLE_NAME = "cosmos";
|
||||
public static final String COLUMN_NAME_TITLE = "phone";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.avapp.contentProvider.primaryNumber;
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Insert;
|
||||
import androidx.room.Query;
|
||||
import androidx.room.Update;
|
||||
import androidx.room.Delete;
|
||||
|
||||
import android.database.Cursor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Dao
|
||||
public interface PrimaryNumberDataDao {
|
||||
@Insert
|
||||
long insert(PrimaryNumberEntity data);
|
||||
|
||||
@Query("SELECT * FROM `primary`")
|
||||
List<PrimaryNumberEntity> getAllData();
|
||||
|
||||
@Query("SELECT * FROM `primary` WHERE id = :id")
|
||||
PrimaryNumberEntity getDataById(int id);
|
||||
|
||||
@Query("SELECT * FROM `primary` WHERE phoneNumber = :phoneNumber LIMIT 1")
|
||||
PrimaryNumberEntity getDataByPhone(String phoneNumber);
|
||||
|
||||
@Query("SELECT * FROM `primary` WHERE phoneNumber = :phoneNumber LIMIT 1")
|
||||
Cursor getDataByPhoneCursor(String phoneNumber);
|
||||
|
||||
@Query("DELETE FROM `primary`")
|
||||
void deleteAllRows();
|
||||
|
||||
@Query("SELECT DISTINCT COUNT(*) FROM `primary`")
|
||||
int getTableLength();
|
||||
|
||||
@Update
|
||||
int update(PrimaryNumberEntity data);
|
||||
|
||||
@Delete
|
||||
int delete(PrimaryNumberEntity data);
|
||||
|
||||
@Query("DELETE FROM `primary` WHERE phoneNumber = :phoneNumber")
|
||||
int deleteDataByPhone(String phoneNumber);
|
||||
|
||||
// Custom methods to return Cursor for Content Provider
|
||||
@Query("SELECT * FROM `primary`")
|
||||
Cursor getAllDataCursor();
|
||||
|
||||
@Query("SELECT * FROM `primary` WHERE id = :id")
|
||||
Cursor getDataByIdCursor(int id);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.avapp.contentProvider.primaryNumber;
|
||||
import androidx.room.PrimaryKey;
|
||||
import androidx.room.Entity;
|
||||
|
||||
@Entity(tableName = "primary")
|
||||
public class PrimaryNumberEntity {
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
public int id;
|
||||
|
||||
public String phoneNumber;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.avapp.sharedPreference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.util.Log;
|
||||
|
||||
import com.facebook.react.bridge.Promise;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
|
||||
public class SharedPreferencesModule extends ReactContextBaseJavaModule {
|
||||
|
||||
private static final String PREFS_NAME = "MyPrefs";
|
||||
private ReactApplicationContext reactApplicationContext;
|
||||
private SharedPreferences sharedPreferences;
|
||||
|
||||
public SharedPreferencesModule(ReactApplicationContext reactContext) {
|
||||
super(reactContext);
|
||||
this.reactApplicationContext = reactContext;
|
||||
sharedPreferences = reactContext.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "SharedPreferencesModule";
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void saveString(String key, String value) {
|
||||
try {
|
||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||
editor.putString(key, value);
|
||||
Log.d("SharedPreferences", "SharedPreferences New Val" + value);
|
||||
Log.d("SharedPreferences", "SharedPreferences editor" + editor);
|
||||
editor.apply();
|
||||
} catch (Exception e) {
|
||||
Log.d("SharedPreferences", "SharedPreferences Exception" + e);
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void getString(String key, String defaultValue, Promise promise) {
|
||||
try {
|
||||
String value = sharedPreferences.getString(key, defaultValue);
|
||||
promise.resolve(value);
|
||||
} catch (Exception e) {
|
||||
promise.reject(e);
|
||||
}
|
||||
}
|
||||
@ReactMethod
|
||||
public void removeKey(String key, Promise promise) {
|
||||
try {
|
||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||
editor.remove(key);
|
||||
editor.apply();
|
||||
promise.resolve(null);
|
||||
} catch (Exception e) {
|
||||
promise.reject(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.avapp.sharedPreference;
|
||||
import com.facebook.react.ReactPackage;
|
||||
import com.facebook.react.bridge.NativeModule;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.uimanager.ViewManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class SharedPreferencesPackage implements ReactPackage {
|
||||
@Override
|
||||
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NativeModule> createNativeModules(
|
||||
ReactApplicationContext reactContext) {
|
||||
List<NativeModule> modules = new ArrayList<>();
|
||||
|
||||
modules.add(new SharedPreferencesModule(reactContext));
|
||||
|
||||
return modules;
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,8 @@ buildscript {
|
||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.2'
|
||||
classpath 'com.google.firebase:perf-plugin:1.4.2'
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#Fri Feb 14 13:50:09 IST 2025
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-all.zip
|
||||
networkTimeout=10000
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
Reference in New Issue
Block a user