Thursday, 28 July 2016

java - Struggling with JDBC in Android Studio



I'm trying to run a stored procedure on my SQL Server database from an Android app I've developed. I'm just messing about at the minute but I can't seem to get it to run. Thing is I don't get any kind of errors or crashes either - the app works fine and I can click the button, the stored procedure just doesn't seem to want to run.



The SP creates a row in a table. I've tested this in SQL server and it works perfectly. The issue seems to be with executing it from my app..



I think I've set things up correctly.



1) I've included the correct .jar file in the libs folder for my app.




2) I've included a reference to the library in build.gradle:-



dependencies {
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:design:23.1.1'
compile 'com.google.android.gms:play-services:8.3.0'
compile fileTree(dir: 'libs', include: ['*.jar'])
compile files('libs/jtds-1.3.1.jar')

}


3) I've imported all of the libraries that I need (I think):-



import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;



4) I've got a button that, when clicked should run the stored procedure:-



@Override
public void onClick(View v) {
try {
Class.forName("net.sourceforge.jtds.jdbc.Driver").newInstance();
String username = "myusername";
String password = "mypassword";

Connection DbConn = DriverManager.getConnection("jdbc:jtds:sqlserver://sql9.hostinguk.net/matprichardson;user=" + username + ";password=" + password);

Log.w("Connection","Open");
Statement stmt = DbConn.createStatement();
stmt.execute("exec [matprichardson].[updatelatlong]");

DbConn.close();
} catch (Exception e) {
Log.w("Error connection","" + e.getMessage());
}

}


If I remove the code from the try/catch blocks, the Class.forName part highlights in red and when I hover I get a java.lang.ClassNotFoundException but I've read that's the reason for the try/catch block in the first place...am I right?



Anyway, after tinkering about with this for an hour I've reached a point where I don't know what to do anymore. Hope you guys can help.



Note: I'm running the app directly on my device rather than through an emulator.



Another note: In the 'logcat' part of Android Monitor I get an error. Full log when I click the button:




11-28 22:54:29.173 11995-11995/uk.co.matprichardson.omgandroid D/libc: [NET] android_getaddrinfofornet+,hn 18(0x73716c372e686f),sn(),hints(known),family 0,flags 4
11-28 22:54:29.173 11995-11995/uk.co.matprichardson.omgandroid D/libc: [NET] android_getaddrinfofornet-, err=8
11-28 22:54:29.173 11995-11995/uk.co.matprichardson.omgandroid E/MYAPP: exception android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1155)
at java.net.InetAddress.lookupHostByName(InetAddress.java:418)
at java.net.InetAddress.getAllByNameImpl(InetAddress.java:252)
at java.net.InetAddress.getAllByName(InetAddress.java:215)
at java.net.Socket.tryAllAddresses(Socket.java:109)
at java.net.Socket.(Socket.java:178)

at java.net.Socket.(Socket.java:150)
at net.sourceforge.jtds.jdbc.SharedSocket.(SharedSocket.java:259)
at net.sourceforge.jtds.jdbc.ConnectionJDBC2.(ConnectionJDBC2.java:311)
at net.sourceforge.jtds.jdbc.Driver.connect(Driver.java:187)
at java.sql.DriverManager.getConnection(DriverManager.java:179)
at java.sql.DriverManager.getConnection(DriverManager.java:144)
at uk.co.matprichardson.omgandroid.MainActivity.onClick(MainActivity.java:114)
at android.view.View.performClick(View.java:4785)
at android.view.View$PerformClick.run(View.java:19869)
at android.os.Handler.handleCallback(Handler.java:739)

at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:155)
at android.app.ActivityThread.main(ActivityThread.java:5721)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1029)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:824)

Answer



This is not entirely right.




catch (Exception e)
{
Log.w("Error connection","" + e.getMessage());
}




11-26 20:49:14.662 5445-5445/uk.co.matprichardson.omgandroid W/Error connection: null



As usual, the answer is in the full stack trace, not in only the exception message. You're basically suppressing the whole exception including its stack trace and only logging the sole exception message. This is really unhelpful (not only for us in order to translate it into layman's terms in case you didn't understand it, but also for yourself in order to research/google it).



In case you have no idea how to print the full stack trace in Android, head to among others the following Q&A: Android - print full exception backtrace to log.



Once having the full stack trace at hands which should look like below:



android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1155)

at java.net.InetAddress.lookupHostByName(InetAddress.java:418)
at java.net.InetAddress.getAllByNameImpl(InetAddress.java:252)
at java.net.InetAddress.getAllByName(InetAddress.java:215)
at java.net.Socket.tryAllAddresses(Socket.java:109)
at java.net.Socket.(Socket.java:178)
at java.net.Socket.(Socket.java:150)
at net.sourceforge.jtds.jdbc.SharedSocket.(SharedSocket.java:259)
at net.sourceforge.jtds.jdbc.ConnectionJDBC2.(ConnectionJDBC2.java:311)
at net.sourceforge.jtds.jdbc.Driver.connect(Driver.java:187)
at java.sql.DriverManager.getConnection(DriverManager.java:179)

at java.sql.DriverManager.getConnection(DriverManager.java:144)
at uk.co.matprichardson.omgandroid.MainActivity.onClick(MainActivity.java:114)
at android.view.View.performClick(View.java:4785)
at android.view.View$PerformClick.run(View.java:19869)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:155)
at android.app.ActivityThread.main(ActivityThread.java:5721)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)

at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1029)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:824)


Then simply copypaste the exception type, message (if any) and 1st line of stack trace (without the parentheses and line number), like below,



android.os.NetworkOnMainThreadException at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork


Into a decent search engine for clues, like Google. As of now, the top hits directly or indirectly (duplicate) refer the below questions:






Surely one of them must have explained/answered your concrete problem.


No comments:

Post a Comment

c++ - Does curly brackets matter for empty constructor?

Those brackets declare an empty, inline constructor. In that case, with them, the constructor does exist, it merely does nothing more than t...