I am doing an app where I have questions displayed and I have stored the next question number in a database so the user can resume whenever they wanted.
My problem here is I fetch the next question number from the DB and append the number to a String variable so then goNextQuestion is equal to Question# (# being the number from the DB).
I then want to pass that variable, for example it is equal to Question2, to the new Intent function to load the activity associated with that question.
Here is the code from Home.class:
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
final String goQuestion = "Question" + lastQuestion";
startActivity(new Intent(Home.this, Class.forName(goQuestion)));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
});
The full Home.class can be viewed here: https://pastebin.com/6mbrBpQm
My expected result would be it wil load the same way as it would if I just passed Question2.class into the Intent. However, there is an error and the catch statement is always executed with the following error:
W/System.err: java.lang.ClassNotFoundException: Question2.class
at java.lang.Class.classForName(Native Method)
at java.lang.Class.forName(Class.java:400)
at java.lang.Class.forName(Class.java:326)
at uk.co.jrtevents.k_quiz.Home$1.onClick(Home.java:45)
W/System.err: at android.view.View.performClick(View.java:5610)
at android.view.View$PerformClick.run(View.java:22265)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
Caused by: java.lang.ClassNotFoundException: Didn't find class "Question2.class" on path: DexPathList[[zip file "/data/app/uk.co.jrtevents.k_quiz-1/base.apk"],nativeLibraryDirectories=[/data/app/uk.co.jrtevents.k_quiz-1/lib/x86, /system/lib, /vendor/lib]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
at java.lang.ClassLoader.loadClass(ClassLoader.java:380)
at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
... 13 more
What would be the best way to resolve this?
Link to Question2.class: https://pastebin.com/5sdsc1Ec
you can try something like below.
if you use the Simple class name like Step8CompletedActivity then it will give the error.
var clazz =
Class.forName(Step8CompletedActivity::class.java.simpleName!!).kotlin as KClass<Activity>
below error will come
java.lang.ExceptionInInitializerError
at com.google.samples.motionlayoutcodelab.MainActivityKt.access$getData$p(MainActivity.kt:1)
at com.google.samples.motionlayoutcodelab.MainActivity.onCreate(MainActivity.kt:114)
at android.app.Activity.performCreate(Activity.java:6662)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2599)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
Caused by: java.lang.ClassNotFoundException: Step8CompletedActivity
at java.lang.Class.classForName(Native Method)
at java.lang.Class.forName(Class.java:400)
at java.lang.Class.forName(Class.java:326)
at com.google.samples.motionlayoutcodelab.MainActivityKt.<clinit>(MainActivity.kt:39)
at com.google.samples.motionlayoutcodelab.MainActivityKt.access$getData$p(MainActivity.kt:1)
instead of using the simple name only use Canonical name or Full name with path
var clazz =
Class.forName(Step8CompletedActivity::class.java.canonicalName!!).kotlin as KClass<Activity>
or using below will produce the same results.
var clazz =
Class.forName("com.google.samples.motionlayoutcodelab.Step8CompletedActivity").kotlin as KClass<Activity>
You don't have put .class
final String goQuestion = "Question" + lastQuestion;
Try this
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
final String goQuestion = "Question" + lastQuestion;
startActivity(new Intent(Home.this, Class.forName(goQuestion)));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
});
Related
I'm trying to connect an Android Studio app to a remote MYSQL database but an error is displaying that couldn't create a connection to the database.
Some troubleshooting I did:
Reviewed if the database is running (it is)
Connected from MySQL workbench in my computer to the remote database (I was able to connect and retrieve data)
Also I was developing another app (no Android Studio). I used the same connection classes and I was able to access the data.
--- With this, I think that is not a server issue. ---
Used different JDBC drivers (Gradle implementation below of the versions I used)
implementation group: 'mysql', name: 'mysql-connector-java', version: '8.0.22'
implementation group: 'mysql', name: 'mysql-connector-java', version: '8.0.23'
implementation group: 'mysql', name: 'mysql-connector-java', version: '8.0.13'
I also tried to add the .jar file in the project files but had other errors that didn't recognized the driver.
--- With this, I noticed that implementing the driver in Gradle is not an error as apparently it is recognizing the driver ---
Note: I'm currently using the gradle implementation.
I added the internet permissions to the AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
I tried to implement the code that retrieves the data from the data base using an ASYNCTASK but received the following errors
Main class WITH ASYNCTASK (MainActivity.java)*
Note: The code in this class was just to test if I was able to get the data from the database. Is not regarding to any functionality I was trying to implement in the app itself.
public class MainActivity extends AppCompatActivity {
AlertDialog.Builder builder;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle("Data");
new GetCultivos().execute();
builder.setPositiveButton("Accept", null);
AlertDialog dialog = builder.create();
dialog.show();
}
});
class GetCultivos extends AsyncTask<Void, Void, Void>{
String list = "Data = ";
#Override
protected Void doInBackground(Void... voids) {
CultivoDao cultivoDao = new CultivoDao();
List<Cultivo> listaCultivos = cultivoDao.obtenerCultivos();
for (Cultivo i : listaCultivos){
list = i.getIdCultivo() + " " + i.getNombre() + ", ";
}
return null;
}
#Override
protected void onPostExecute(Void eVoid){
builder.setMessage(list);
}
}
}
E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
Process: com.example.appmov, PID: 5699
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$4.done(AsyncTask.java:399)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
at java.util.concurrent.FutureTask.run(FutureTask.java:271)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:289)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
Caused by: java.lang.NoClassDefFoundError: Failed resolution of: Ljava/sql/SQLType;
at com.mysql.cj.jdbc.DatabaseMetaData.getInstance(DatabaseMetaData.java:729)
at com.mysql.cj.jdbc.ConnectionImpl.getMetaData(ConnectionImpl.java:1180)
at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:446)
at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:240)
at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:207)
at java.sql.DriverManager.getConnection(DriverManager.java:580)
at java.sql.DriverManager.getConnection(DriverManager.java:218)
at com.DAO.appmov.CultivoDao.StartConnection(CultivoDao.java:30)
at com.DAO.appmov.CultivoDao.obtenerCultivos(CultivoDao.java:49)
at com.example.appmov.MainActivity$GetCultivos.doInBackground(MainActivity.java:228)
at com.example.appmov.MainActivity$GetCultivos.doInBackground(MainActivity.java:220)
at android.os.AsyncTask$3.call(AsyncTask.java:378)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:289)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
Caused by: java.lang.ClassNotFoundException: Didn't find class "java.sql.SQLType" on path: DexPathList[[zip file "/data/app/com.example.appmov-U33MrmDYU8kMl3MFpFCdcA==/base.apk"],nativeLibraryDirectories=[/data/app/com.example.appmov-U33MrmDYU8kMl3MFpFCdcA==/lib/arm64, /system/lib64]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:196)
at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
at com.mysql.cj.jdbc.DatabaseMetaData.getInstance(DatabaseMetaData.java:729)
at com.mysql.cj.jdbc.ConnectionImpl.getMetaData(ConnectionImpl.java:1180)
at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:446)
at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:240)
at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:207)
at java.sql.DriverManager.getConnection(DriverManager.java:580)
at java.sql.DriverManager.getConnection(DriverManager.java:218)
at com.DAO.appmov.CultivoDao.StartConnection(CultivoDao.java:30)
at com.DAO.appmov.CultivoDao.obtenerCultivos(CultivoDao.java:49)
at com.example.appmov.MainActivity$GetCultivos.doInBackground(MainActivity.java:228)
at com.example.appmov.MainActivity$GetCultivos.doInBackground(MainActivity.java:220)
at android.os.AsyncTask$3.call(AsyncTask.java:378)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:289)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
I/Process: Sending signal. PID: 5699 SIG: 9
So I tried to implement the code without an ASYNCTASK, but I'm receiving the error that you can see below in the error log.
Class I use to connect to the database (CultivoDao.java)
public class CultivoDao {
private Connection connection;
private Statement statement;
//Method to start the connection
private void StartConnection() {
String url = "jdbc:mysql://remotemysql.com:3306/hUfMa4wLpe";
String usuario = ***HERE IS THE USERNAME***;
String password = ***HERE IS THE PASSWORD***;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
connection = DriverManager.getConnection(url, usuario, password);
statement = connection.createStatement();
} catch (Exception e) {
e.printStackTrace();
}
}
//Method to close the connection
private void CloseConnection(){
try {
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
//Methog to get the data
public List<Cultivo> obtenerCultivos(){
List<Cultivo> listaCultivos = new ArrayList<>();
try {
StartConnection();
ResultSet rs = statement.executeQuery("Select * from cultivo");
while(rs.next()){
Cultivo cultivo = new Cultivo(rs.getInt("idCultivo"), rs.getString("nombre"));
listaCultivos.add(cultivo);
}
}catch (Exception e){
e.printStackTrace();
}
CloseConnection();
return listaCultivos;
}
}
Main class WITHOUT ASYNCTASK (MainActivity.java)*
Note: The code in this class was just to test if I was able to get the data from the database. Is not regarding to any functionality I was trying to implement in the app itself.
public class MainActivity extends AppCompatActivity {
AlertDialog.Builder builder;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
builder = new AlertDialog.Builder(MainActivity.this);
String list = "Database list = ";
CultivoDao cultivoDao = new CultivoDao();
List<Cultivo> listaCultivos = cultivoDao.obtenerCultivos();
for (Cultivo i : listaCultivos){
list = i.getIdCultivo() + " " + i.getNombre() + ", ";
}
builder.setTitle("Data");
builder.setMessage(list);
builder.setPositiveButton("Accept", null);
AlertDialog dialog = builder.create();
dialog.show();
}
});
}
}
The actual version I'm using is the one without the ASYNCTASK
I'm testing this app in a physical device. I don't know that this can affect in some way.
Error log:
W/System.err: java.sql.SQLNonTransientConnectionException: Could not create connection to database server.
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:110)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
W/System.err: at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:89)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:63)
at com.mysql.cj.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:1008)
at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:825)
at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:455)
at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:240)
at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:207)
at java.sql.DriverManager.getConnection(DriverManager.java:580)
at java.sql.DriverManager.getConnection(DriverManager.java:218)
at com.DAO.appmov.CultivoDao.StartConnection(CultivoDao.java:30)
at com.DAO.appmov.CultivoDao.obtenerCultivos(CultivoDao.java:49)
at com.example.appmov.MainActivity$1.onClick(MainActivity.java:88)
at android.view.View.performClick(View.java:7870)
at android.widget.TextView.performClick(TextView.java:14970)
at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:967)
at android.view.View.performClickInternal(View.java:7839)
at android.view.View.access$3600(View.java:886)
at android.view.View$PerformClick.run(View.java:29363)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:237)
at android.app.ActivityThread.main(ActivityThread.java:7814)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1068)
W/System.err: Caused by: android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1565)
at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:115)
at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:103)
at java.net.InetAddress.getAllByName(InetAddress.java:1152)
at com.mysql.cj.protocol.StandardSocketFactory.connect(StandardSocketFactory.java:132)
at com.mysql.cj.protocol.a.NativeSocketConnection.connect(NativeSocketConnection.java:65)
at com.mysql.cj.NativeSession.connect(NativeSession.java:152)
at com.mysql.cj.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:955)
... 22 more
java.lang.NullPointerException: Attempt to invoke interface method 'java.sql.ResultSet java.sql.Statement.executeQuery(java.lang.String)' on a null object reference
at com.DAO.appmov.CultivoDao.obtenerCultivos(CultivoDao.java:50)
at com.example.appmov.MainActivity$1.onClick(MainActivity.java:88)
at android.view.View.performClick(View.java:7870)
at android.widget.TextView.performClick(TextView.java:14970)
W/System.err: at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:967)
at android.view.View.performClickInternal(View.java:7839)
at android.view.View.access$3600(View.java:886)
at android.view.View$PerformClick.run(View.java:29363)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:237)
at android.app.ActivityThread.main(ActivityThread.java:7814)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1068)
java.lang.NullPointerException: Attempt to invoke interface method 'void java.sql.Connection.close()' on a null object reference
at com.DAO.appmov.CultivoDao.CloseConnection(CultivoDao.java:40)
at com.DAO.appmov.CultivoDao.obtenerCultivos(CultivoDao.java:58)
at com.example.appmov.MainActivity$1.onClick(MainActivity.java:88)
at android.view.View.performClick(View.java:7870)
at android.widget.TextView.performClick(TextView.java:14970)
at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:967)
at android.view.View.performClickInternal(View.java:7839)
at android.view.View.access$3600(View.java:886)
at android.view.View$PerformClick.run(View.java:29363)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:237)
at android.app.ActivityThread.main(ActivityThread.java:7814)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1068)
How can I solve this issue without implementing PHP that is another way I found as I can't edit anything of the server where the database is hosted.
Thanks!
ClassNotFoundException: Didn't find class "java.sql.SQLType"
Since java.sql.SQLType was added in Java 8, and doesn't exist at all on Android, you need to use a JDBC driver that is Java 7 compatible, which means you cannot use Connector/J 8.0, but must use version 5.1.
I started learning Java and I have an app installed on my Android device. The app simply has a MainActivity(com.example.myapplication.MainActivity) only. Inside MainActivity there are a public(doSomething1) and a private(doSomething2) methods. Let's assume that I don't have the source files of the app. What I am going to do is to call those methods from another app(DEX) by using Java Reflection. Here is the code of performing runtime Dex injection.
JNIEnv* (*getJNIEnv)();
/**
* Inject the DEX file and execute the method.
* #param dexPath: The dex file to inject
* #param dexOptDir: Cache path
* #param className: Class name to be executed after injection
* #param methodName: Method name to execute
* #param argc: number of arguments
* #param argv: arguments
* #return
*/
int invoke_dex_method(const char* dexPath, const char* dexOptDir, const char* className, const char* methodName, int argc, char *argv[]) {
LOGD("dexPath = %s, dexOptDir = %s, className = %s, methodName = %s\n", dexPath, dexOptDir, className, methodName);
// Acquisition of JNIEnv
void* handle = dlopen("/system/lib/libandroid_runtime.so", RTLD_NOW);
LOGD("dlopen = %x, %s\n", handle, strerror(errno));
getJNIEnv = dlsym(handle, "_ZN7android14AndroidRuntime9getJNIEnvEv");
LOGD("dlsym = %x, %s\n", getJNIEnv, strerror(errno));
JNIEnv* env = getJNIEnv();
LOGD("JNIEnv = %x\n", env);
// Call getSystemClassLoader of ClassLoader to get ClassLoader of current process
jclass classloaderClass = (*env)->FindClass(env,"java/lang/ClassLoader");
jmethodID getsysloaderMethod = (*env)->GetStaticMethodID(env,classloaderClass, "getSystemClassLoader", "()Ljava/lang/ClassLoader;");
jobject loader = (*env)->CallStaticObjectMethod(env, classloaderClass, getsysloaderMethod);
LOGD("loader = %x\n", loader);
// Read the dex file with DexClassLoader for processing with the current ClassLoader
jstring dexpath = (*env)->NewStringUTF(env, dexPath);
jstring dex_odex_path = (*env)->NewStringUTF(env,dexOptDir);
jclass dexLoaderClass = (*env)->FindClass(env,"dalvik/system/DexClassLoader");
jmethodID initDexLoaderMethod = (*env)->GetMethodID(env, dexLoaderClass, "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)V");
jobject dexLoader = (*env)->NewObject(env, dexLoaderClass, initDexLoaderMethod,dexpath,dex_odex_path,NULL,loader);
LOGD("dexLoader = %x\n", dexLoader);
// Load code to execute using DexClassLoader
jmethodID findclassMethod = (*env)->GetMethodID(env,dexLoaderClass,"findClass","(Ljava/lang/String;)Ljava/lang/Class;");
jstring javaClassName = (*env)->NewStringUTF(env,className);
jclass javaClientClass = (*env)->CallObjectMethod(env,dexLoader,findclassMethod,javaClassName);
if (!javaClientClass) {
LOGD("Failed to load target class %s\n", className);
printf("Failed to load target class %s\n", className);
return -1;
}
// Get the method to inject
jmethodID start_inject_method = (*env)->GetStaticMethodID(env, javaClientClass, methodName, "()V");
if (!start_inject_method) {
LOGD("Failed to load target method %s\n", methodName);
printf("Failed to load target method %s\n", methodName);
return -1;
}
// Execute method (this method must be a public static void method)
(*env)->CallStaticVoidMethod(env,javaClientClass,start_inject_method);
return 0;
}
The above code works well without any problem and the method(4th param) got called. Here is the code of Java class in Dex file.
public class HookTool {
public static final String TAG = "INJECT";
public static void dexInject() throws ClassNotFoundException, IllegalAccessException {
Log.d(TAG, "This is dex code. Start hooking process in Java world.");
try {
Class<?> activityClass = Class.forName("com.example.myapplication.MainActivity");
Method method2 = activityClass.getMethod("doSomething1");
Method method1 = activityClass.getDeclaredMethod("doSomething2");
} catch (ClassNotFoundException | NoSuchMethodException e) {
e.printStackTrace();
}
}
}
I am not getting the expected result from the above code. Here is the logcat result printed.
D/INJECT (15393): This is dex code. Start hooking process in Java world.
W/System.err(15393): java.lang.ClassNotFoundException: com.example.myapplication.MainActivity
W/System.err(15393): at java.lang.Class.classForName(Native Method)
W/System.err(15393): at java.lang.Class.forName(Class.java:309)
W/System.err(15393): at java.lang.Class.forName(Class.java:273)
W/System.err(15393): at net.cimadai.hookerApp.HookTool.dexInject(HookTool.java:43)
W/System.err(15393): at android.os.MessageQueue.nativePollOnce(Native Method)
W/System.err(15393): at android.os.MessageQueue.next(MessageQueue.java:143)
W/System.err(15393): at android.os.Looper.loop(Looper.java:122)
W/System.err(15393): at android.app.ActivityThread.main(ActivityThread.java:5254)
W/System.err(15393): at java.lang.reflect.Method.invoke(Native Method)
W/System.err(15393): at java.lang.reflect.Method.invoke(Method.java:372)
W/System.err(15393): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:905)
W/System.err(15393): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:700)
W/System.err(15393): Caused by: java.lang.ClassNotFoundException: Didn't find class "com.example.myapplication.MainActivity" on path: DexPathList[[zip file "/data/local/tmp/app-debug.apk"],nativeLibraryDirectories=[/vendor/lib, /system/lib]]
W/System.err(15393): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
W/System.err(15393): at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
W/System.err(15393): at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
W/System.err(15393): ... 12 more
W/System.err(15393): Suppressed: java.lang.ClassNotFoundException: Didn't find class "com.example.myapplication.MainActivity" on path: DexPathList[[directory "."],nativeLibraryDirectories=[/vendor/lib, /system/lib]]
W/System.err(15393): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
W/System.err(15393): at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
W/System.err(15393): at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
W/System.err(15393): ... 13 more
W/System.err(15393): Suppressed: java.lang.ClassNotFoundException: com.example.myapplication.MainActivityW/System.err(15393): at java.lang.Class.classForName(Native Method)
W/System.err(15393): at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
W/System.err(15393): at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
W/System.err(15393): at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
W/System.err(15393): ... 14 more
W/System.err(15393): Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available
So questions are
Is it possible to invoke method in an app from another app by using Java Reflection?
If not, what is the approach to getting this work?
Could you someone please explain to me?
Thank you in advance
I found the way to get top activity after dex injection. Here is the code.
public static Activity getTopActivity() {
Activity topActivity = null;
try {
#SuppressLint("PrivateApi") Class activityThreadClass = Class.forName("android.app.ActivityThread");
#SuppressLint("DiscouragedPrivateApi") Method getATMethod = activityThreadClass.getDeclaredMethod("currentActivityThread");
Field activitiesField = activityThreadClass.getDeclaredField("mActivities");
Object activityThread = getATMethod.invoke(null);
activitiesField.setAccessible(true);
Object activityClientRecord;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
ArrayMap activities = (ArrayMap) activitiesField.get(activityThread);
activityClientRecord = activities.valueAt(0);
}else{
HashMap activities = (HashMap) activitiesField.get(activityThread);
activityClientRecord = activities.values();
}
#SuppressLint("PrivateApi") Class activityClientRecordClass = Class.forName("android.app.ActivityThread$ActivityClientRecord");
Field activityField = activityClientRecordClass.getDeclaredField("activity");
activityField.setAccessible(true);
topActivity = (Activity) activityField.get(activityClientRecord);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
return topActivity;
}
The above code will give you the instance of the most top activity.
I'm about to go nuts with this. I keep getting errors when trying to open a text file that's in my assets directory, whose full path name is
C:\Users\Dov\Google Drive\AndroidStudioProjects\WordyHelperton - Copy - Copy\
app\src\main\assets
Even though we can SEE filename Dictionary.dic in the assets folder for my project...
... I keep getting errors that the file doesn't exist:
W/`````: Can't open <Dictionary.dic>
W/System.err: java.io.FileNotFoundException: Dictionary.dic
W/System.err: at android.content.res.AssetManager.openAsset(Native Method)
W/System.err: at android.content.res.AssetManager.open(AssetManager.java:316)
W/System.err: at android.content.res.AssetManager.open(AssetManager.java:290)
W/System.err: at com.dslomer64.servyhelperton.DatabaseConnector$LoadDatabase.doInBackground(DatabaseConnector.java:328)
W/System.err: at com.dslomer64.servyhelperton.DatabaseConnector$LoadDatabase.doInBackground(DatabaseConnector.java:315)
W/System.err: at android.os.AsyncTask$2.call(AsyncTask.java:288)
W/System.err: at java.util.concurrent.FutureTask.run(FutureTask.java:237)
W/System.err: at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
W/System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
W/System.err: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
W/System.err: at java.lang.Thread.run(Thread.java:841)
Doc says you can use hierarchical name in the open statement:
W/`````: Can't open <C:\Users\Dov\Google Drive\AndroidStudioProjects\WordyHelperton - Copy - Copy\app\src\main\assets\Dictionary.dic>
W/System.err: java.io.FileNotFoundException: C:\Users\Dov\Google Drive\AndroidStudioProjects\WordyHelperton - Copy - Copy\app\src\main\assets\Dictionary.dic
W/System.err: at android.content.res.AssetManager.openAsset(Native Method)
W/System.err: at android.content.res.AssetManager.open(AssetManager.java:316)
W/System.err: at android.content.res.AssetManager.open(AssetManager.java:290)
W/System.err: at com.dslomer64.servyhelperton.DatabaseConnector$LoadDatabase.doInBackground(DatabaseConnector.java:330)
W/System.err: at com.dslomer64.servyhelperton.DatabaseConnector$LoadDatabase.doInBackground(DatabaseConnector.java:317)
W/System.err: at android.os.AsyncTask$2.call(AsyncTask.java:288)
Same problem.
Can you see any problem with my code? The problem HAS to be obvious, but after two days of trying this and that and utterly failing, and it LOOKS so good and therefore MUST be obvious, but I CAN'T SEE IT....
I've included this in case it's not obvious from above. If this doesn't help, I'm on my own.
Here is how DatabaseConnector gets called in onCreate in MainActivity:
assets = getAssets();
dbc = new DatabaseConnector(getApplicationContext(), assets); // to create DB if needed
Here's how mAssets and SOURCE_NAME are defined; also have DatabaseConnector definition and its call to dbOpenHelper.
Here's how LoadDatabase is called from createDbIfNecessary:
LoadDatabase
__loadDb;
__loadDb = new LoadDatabase();
__loadDb.execute((Object[]) null);
EDIT
Another opinion:
EDIT 2
Please note that changing the filename in the code to lowercase doesn't help. AND it's a DOS file, NOT ANDROID. AND File is never leaving drive C:
public static String DATABASE_SOURCE =
"C:\\Users\\Dov\\Desktop\\ServyHelperton\\app\\src\\main" +
"\\assets\\dictionary.dic";
W/`````: Can't open <C:\Users\Dov\Desktop\ServyHelperton\app\src\main\assets\dictionary.dic>
W/System.err: java.io.FileNotFoundException: C:\Users\Dov\Desktop\ServyHelperton\app\src\main\assets\dictionary.dic
I could add more code to prove what I just said, but trust me. The DATABASE_SOURCE name is ALL I changed.
It appears your path is for Dictionary.dic rather than dictionary.dic
See if that helps
In the end, the fix was sort of easy or maybe dumb luck, because I'm not sure why making the InputStream and Scanner local to doInBackground cured the problem.
Refer to the first picture in the original Question. I made no significant changes to MainActivity, but here is the interesting line in it:
dbc = new DatabaseConnector(getApplicationContext(), getAssets());
This is what worked:
public class DatabaseConnector
{
static Context mContext;
public DatabaseConnector(Context _context, AssetManager _assets)
{
mAssets = _assets;
mContext = _context;
mDbOpenHelper = new DbOpenHelper(_context, DATABASE_NAME, null, 1);
createDbIfNecessary();
}
private class DbOpenHelper extends SQLiteOpenHelper
{
DbOpenHelper(Context _context, String _name, CursorFactory _factory, int _version)
{
super(_context, _name, _factory, _version);
}
private class LoadDatabase extends AsyncTask<Object, Integer, Void>
{
protected Void doInBackground(Object[] params)
{
Scanner scDict = null; // ***** MOVING/ADDING THESE
InputStream stream; // ***** TWO LINES HERE WAS KEY
try{
stream = mContext.getAssets().open(DATABASE_SOURCE);
scDict = new Scanner(stream).useDelimiter("\r\n");
}
catch(IOException e){e.printStackTrace(); System.exit(69);}
}
}
}
}
I have uploaded file and when I try to get the shared link then it gives NullPointerException.
FileInputStream fis = new FileInputStream(mFile);
String path = mPath + mFile.getName();
DropboxAPI.Entry response = mApi.putFile(path, fis,
mFile.length(), null, new ProgressListener() {
#Override
public long progressInterval() {
// Update the progress bar every half-second or so
return 500;
}
#Override
public void onProgress(long bytes, long total) {
publishProgress(bytes);
}
});
Log.i("DbExampleLog", "The uploaded file's rev is: " + response.rev);
if (response != null) {
mErrorMsg=response.path;
Log.e("DbExampleLog", "*****"+response.path+" The uploaded file's rev is: " + response.rev);
DropboxAPI.DropboxLink shareLink = mApi.share(response.path);
Log.e("DbExampleLog", "*****"+shareLink+" The uploaded file's rev is: " + response.rev);
if(shareLink!=null) {
if(shareLink.url!=null) {
Log.e("Null error URL*****",""+shareLink.url);
Log.e("Null error URL*****",""+getShareURL(shareLink.url));
String shareAddress = getShareURL(shareLink.url).toString();
Log.e("DbExampleLog", "URL -" + shareAddress + "*****" + response.path + " The uploaded file's rev is: " + response.rev);
}
else
Log.e("Null error URL*****",""+shareLink.url);
}
else{
Log.e("Null error*****",""+shareLink);
}
return true;
}
It returns like -
12-05 12:09:09.207 7335-7502/com.trucker.gtd.satyaki.dropboxintegrationapiv1 E/DbExampleLog: *****/1480919937073.jpg The uploaded file's rev is: 2ef4a7ca38e
12-05 12:09:10.966 7335-7502/com.trucker.gtd.satyaki.dropboxintegrationapiv1 E/DbExampleLog: *****com.dropbox.client2.DropboxAPI$DropboxLink#d9d5da1 The uploaded file's rev is: 2ef4a7ca38e
12-05 12:09:10.966 7335-7502/com.trucker.gtd.satyaki.dropboxintegrationapiv1 E/Null error URL*****: https://db.tt/ru6e39XK0
12-05 12:09:12.457 7335-7502/com.trucker.gtd.satyaki.dropboxintegrationapiv1 E/Null error URL*****: null
12-05 12:09:13.520 7335-7502/com.trucker.gtd.satyaki.dropboxintegrationapiv1 E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
Process: com.trucker.gtd.satyaki.dropboxintegrationapiv1, PID: 7335
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:318)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:761)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.String.toString()' on a null object reference
at com.trucker.gtd.satyaki.dropboxintegrationapiv1.UploadFile.doInBackground(UploadFile.java:147)
at com.trucker.gtd.satyaki.dropboxintegrationapiv1.UploadFile.doInBackground(UploadFile.java:63)
at android.os.AsyncTask$2.call(AsyncTask.java:304)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:761)
12-05 12:09:13.645 1248-1248/? E/EGL_emulation: tid 1248: eglCreateSyncKHR(1641): error 0x3004 (EGL_BAD_ATTRIBUTE)
12-05 12:09:13.796 2071-2205/com.android.launcher3 E/EGL_emulation: tid 2205: eglSurfaceAttrib(1146): error 0x3009 (EGL_BAD_MATCH)
12-05 12:09:14.006 1530-1640/system_process E/EGL_emulation: tid 1640: eglSurfaceAttrib(1146): error 0x3009 (EGL_BAD_MATCH)
12-05 12:09:14.304 7335-7335/com.trucker.gtd.satyaki.dropboxintegrationapiv1 E/WindowManager: android.view.WindowLeaked: Activity com.trucker.gtd.satyaki.dropboxintegrationapiv1.Main has leaked window DecorView#3bf9cac[] that was originally added here
at android.view.ViewRootImpl.<init>(ViewRootImpl.java:417)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:331)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93)
at android.app.Dialog.show(Dialog.java:316)
at android.app.AlertDialog$Builder.show(AlertDialog.java:1112)
at com.dropbox.client2.android.AuthActivity.checkAppBeforeAuth(AuthActivity.java:284)
at com.dropbox.client2.android.AndroidAuthSession.startAuthentication(AndroidAuthSession.java:213)
at com.trucker.gtd.satyaki.dropboxintegrationapiv1.Main.onActivityResult(Main.java:132)
at android.app.Activity.dispatchActivityResult(Activity.java:6915)
at android.app.ActivityThread.deliverResults(ActivityThread.java:4049)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4096)
at android.app.ActivityThread.-wrap20(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1516)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
12-05 12:09:14.310 7335-7335/com.trucker.gtd.satyaki.dropboxintegrationapiv1 E/WindowManager: android.view.WindowLeaked: Activity com.trucker.gtd.satyaki.dropboxintegrationapiv1.Main has leaked window DecorView#e8ad10a[] that was originally added here
at android.view.ViewRootImpl.<init>(ViewRootImpl.java:417)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:331)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93)
at android.app.Dialog.show(Dialog.java:316)
at com.trucker.gtd.satyaki.dropboxintegrationapiv1.UploadFile.<init>(UploadFile.java:98)
at com.trucker.gtd.satyaki.dropboxintegrationapiv1.Main.setLoggedIn(Main.java:144)
at com.trucker.gtd.satyaki.dropboxintegrationapiv1.Main.onResume(Main.java:168)
at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1269)
at android.app.Activity.performResume(Activity.java:6766)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3377)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3440)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1510)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
Mainly in this particular line-
getShareURL(shareLink.url)
Please suggest me why this error occur, but yesterday using this code it worked.
UPDATE CODE ASKED BY Greg
String getShareURL(String strURL) {
URLConnection conn = null;
String redirectedUrl = null;
try {
URL inputURL = new URL(strURL);
conn = inputURL.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
System.out.println("Redirected URL: " + conn.getURL());
Log.e("Get Redirected URL",""+conn.getURL());
redirectedUrl = conn.getURL().toString();
is.close();
} catch (MalformedURLException e) {
Log.e("TAG", "Please input a valid URL");
} catch (IOException ioe) {
Log.e("TAG", "Can not connect to the URL");
}
return redirectedUrl;
}
This code taken from Share file in Dropbox
I have a file called "and.doc" that has big number of records each one has this shape
expression : defenition ;
So I'm trying to
Read the file with scanner
use ; as a delimiter
find a way to split expression from definition
and somehow add them to my Sqlite Database (if someone have any idea how to do that it will be great).
I'm using this code
try {
mf =new File("/home/agh/AndroidStudioProjects/Dicod/app/src/main/res/raw/and.doc");
inputFile = new Scanner(mf);
inputFile.useDelimiter(";");
while (inputFile.hasNext())
{
String x = inputFile.next();
Toast.makeText(getApplicationContext(),x,Toast.LENGTH_LONG).show();
//Splitting and adding to the databse
}
}
catch(FileNotFoundException e) {
e.printStackTrace();
}`
But I keep getting this error
06-23 04:38:28.771 23620-23620/? W/System.err: java.io.FileNotFoundException: /home/agh/AndroidStudioProjects/Dicod/app/src/main/res/raw/and.txt: open failed: ENOENT (No such file or directory)
06-23 04:38:28.771 23620-23620/? W/System.err: at libcore.io.IoBridge.open(IoBridge.java:465)
06-23 04:38:28.771 23620-23620/? W/System.err: at java.io.FileInputStream.<init>(FileInputStream.java:76)
06-23 04:38:28.771 23620-23620/? W/System.err: at java.util.Scanner.<init>(Scanner.java:158)
06-23 04:38:28.772 23620-23620/? W/System.err: at java.util.Scanner.<init>(Scanner.java:138)
06-23 04:38:28.772 23620-23620/? W/System.err: at com.example.agh.dicod.MainActivity.onCreate(MainActivity.java:28)
06-23 04:38:28.772 23620-23620/? W/System.err: at android.app.Activity.performCreate(Activity.java:5990)
06-23 04:38:28.772 23620-23620/? W/System.err: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
06-23 04:38:28.772 23620-23620/? W/System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2332)
06-23 04:38:28.772 23620-23620/? W/System.err: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2442)
06-23 04:38:28.772 23620-23620/? W/System.err: at android.app.ActivityThread.access$800(ActivityThread.java:156)
06-23 04:38:28.772 23620-23620/? W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1351)
06-23 04:38:28.772 23620-23620/? W/System.err: at android.os.Handler.dispatchMessage(Handler.java:102)
06-23 04:38:28.772 23620-23620/? W/System.err: at android.os.Looper.loop(Looper.java:211)
06-23 04:38:28.772 23620-23620/? W/System.err: at android.app.ActivityThread.main(ActivityThread.java:5389)
06-23 04:38:28.772 23620-23620/? W/System.err: at java.lang.reflect.Method.invoke(Native Method)
06-23 04:38:28.772 23620-23620/? W/System.err: at java.lang.reflect.Method.invoke(Method.java:372)
06-23 04:38:28.772 23620-23620/? W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1020)
06-23 04:38:28.772 23620-23620/? W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:815)
06-23 04:38:28.772 23620-23620/? W/System.err: Caused by: android.system.ErrnoException: open failed: ENOENT (No such file or directory)
06-23 04:38:28.773 23620-23620/? W/System.err: at libcore.io.Posix.open(Native Method)
06-23 04:38:28.773 23620-23620/? W/System.err: at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)
06-23 04:38:28.773 23620-23620/? W/System.err: at libcore.io.IoBridge.open(IoBridge.java:451)
06-23 04:38:28.773 23620-23620/? W/System.err: ... 17 more
Maybe the file doesn't exist in the selected directory or the READ_EXTERNAL_STORAGE permission is not granted.
Notice that if you target API 23, you have to request for permission on runtime, not only in the Manifest.
http://developer.android.com/training/permissions/requesting.html
The File doesn't exist. Create file using File() class and write the stream to it. Then read the data from it. Try adding the permission to the Manifest.xml and give a try.
<manifest ...>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
/>
...
</manifest>
I think the directory that you are passing
"/home/agh/AndroidStudioProjects/Dicod/app/src/main/res/raw/and.doc"
is present on your computer but the File is expecting the directory from your android device or android emulator that is the reason it is throwing an exception
if your "and.doc" is present in shared external storage of your android device "/storage/emulated/0/Documents/" then I think File will be able to access it given that you extract the directory correctly
here is how you can get the directory of your documents folder present in your sd card as an example
File externalStorageDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS); //getting external storage directory
//it's another method to get the directory of a file inside the external storage of a device
File folder = new File(externalStorageDirectory + "/Password");
instead of "/Password" replace it with your folder name
#Abdul2511 i'm not sure i understand the write stream part
I think What he meant was this although the code below will read the text file contents present in the directory
File myfile that is passed as a Parameter should be the extracted directory
// getdata() is the method which reads the data
// the data that is saved in byte format in the file
private String getdata(File myfile) {
FileInputStream fileInputStream = null;
try {
Log.i("file_read_send_to_getData_function",myfile.toString());
fileInputStream = new FileInputStream(myfile);
int i = -1;
StringBuffer buffer = new StringBuffer();
while ((i = fileInputStream.read()) != -1) {
buffer.append((char) i);
}
return buffer.toString();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
#Abdul2511 and somehow add them to my Sqlite Database
Here's a sample code that you can use as a reference on how to save and retrieve data from SQLite database on Android devices.
Root class of our SQLite database is SQLiteOpenHelper.
extends SQLiteOpenHelper will import that root class of SQLite database into our database class
// root class of our SQLite database is SQLiteOpenHelper
// extends SQLiteOpenHelper will import that root class of SQLite database into our NoteDatabase class
public class NoteDatabase extends SQLiteOpenHelper {
private static final int DATABASEVERSION= 2;
private static final String DATABASE_NAME = "your database name";
private static final String DATABASE_TABLE = "your table name";
//column names for database
private static final String KEY_ID="id";
private static final String KEY_TITLE="expression";
private static final String KEY_CONTENT="defenition";
private static final String KEY_DATE="date";
private static final String KEY_TIME="time";
public static List<Note> allNotes;
//creating a constructor for our noteDatabase
NoteDatabase(Context context){
super(context,DATABASE_NAME,null,DATABASEVERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
//onCreate is called every time the noteDatabase instance is created inside any class of this application
//creating the database table
String query = "CREATE TABLE " + DATABASE_TABLE +" ("+ KEY_ID +" INTEGER PRIMARY KEY AUTOINCREMENT , "+
KEY_TITLE+" TEXT, "+
KEY_CONTENT+" TEXT, "+
KEY_DATE+" TEXT, "+
KEY_TIME+" TEXT "+")";
db.execSQL(query);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//checking for updates for our database
if(oldVersion>=newVersion){
return;
}
else{
//update the table if new version is available
db.execSQL("DROP TABLE IF EXISTS "+DATABASE_TABLE);
onCreate(db);
}
}
//it will take Note as a parameter this note will contain all the information like title, content , date and time
//and it will send that note from addnote activity to this node database
//Note note is the class that we just created
public long addnote(Note note){
//here we will insert the data
SQLiteDatabase db = this.getWritableDatabase();
//this contentValues will create a dictionary like structure
ContentValues contentValues = new ContentValues();
//now we can save our value to the keys that we have created in this class
// contentValues.put(KEY_ID,note.getID()); ***Do not insert Id inside SQLite instead auto increment the id to be unique
contentValues.put(KEY_TITLE,note.getTitle());
contentValues.put(KEY_CONTENT,note.getContent());
contentValues.put(KEY_TIME,note.getTime());
contentValues.put(KEY_DATE,note.getDate());
//now we will insert the data
//if the data is inserted successfully it will return the long value of the primary key
long ID = db.insert(DATABASE_TABLE,null,contentValues);
db.close();
Log.i("ID", Long.toString(ID));
return ID;
}
//this will get all the notes present in the database
//so that we can desplay it in our ListView
public List<Note> getNotes(){
//we will pull the data from the database using element's unique id
//select * from databse where id = whatever the id we have passed on here
//* means acessing all the data in that particular id elements
//creating an instance of our database
SQLiteDatabase db = this.getReadableDatabase();
//creating a list of generic type called Note
allNotes = new ArrayList<>();
String query = "SELECT * FROM "+DATABASE_TABLE;
Cursor cursor = db.rawQuery(query,null);
if(cursor.moveToFirst()){
//i am going to pull all the data from the database and pass that data onto our listView
do{
//now creating a new note and save the data from the database by using cursor
Note note = new Note();
note.setID(cursor.getLong(0));
note.setTitle(cursor.getString(1));
note.setContent(cursor.getString(2));
note.setDate(cursor.getString(3));
note.setTime(cursor.getString(4));
//adding this to lisView
allNotes.add(note);
}while(cursor.moveToNext());
}
return allNotes;
}
//updating the database
//replacing the old data with the updated data set inside the database
public int editNote(Note note){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(KEY_TITLE,note.getTitle());
contentValues.put(KEY_CONTENT,note.getContent());
contentValues.put(KEY_DATE,note.getDate());
contentValues.put(KEY_TIME,note.getTime());
return db.update(DATABASE_TABLE, contentValues,KEY_ID+"=?",new String[]{String.valueOf(note.getID())});
}
//the method will handel the deletion of the notes
//this method will be called from the noteDetails.class
void deleteNote(long id){
SQLiteDatabase db = this.getWritableDatabase();
db.delete(DATABASE_TABLE,KEY_ID+"=?",new String[]{String.valueOf(id)});
db.close();
}
}
Note:-
You will have to modify the code according to your needs this only deals with writing the data onto the database and reading from the database
create a separate getter and setter java file in order to act as an adapter between your activity and the database
this is just a sample code from my own project
I am assuming that you have already separated expression into a separate string variable from definition