因此,我一直在使用此功能进行开/关工作几天,感觉好像我已经用尽了所有相关的搜索字词一样。首先,我说我对此进行了大量研究,但没有成功。我得出的结论是,它要么是非常异常的(不太可能),要么是我以某种方式忽略了的微小细节。我还要马上说,是的,我知道直接从应用程序连接到数据库不是理想的,我应该使用Web服务器,但是出于我的意图和目的,此解决方案不是问题。
我知道这篇文章很长,但是我很感谢大家的时间。如果没有其他要求,至少它可以帮助最近刚开始使用JDBC并开始遇到问题的其他人。 “我尝试过的”部分概述了您可以在网上找到的大部分尝试内容。
我正在尝试做的是:
使用JDBC驱动程序,通过Android Studio连接到我的Azure托管的SqlServer数据库。
我遇到的错误:
W/System.err: com.microsoft.sqlserver.jdbc.SQLServerException: The TCP/IP connection to the host vet-to-go.database.windows.net, port 1433 has failed. Error: "Connection timed out: no further information. Verify the connection properties. Make sure that an instance of SQL Server is running on the host and accepting TCP/IP connections at the port. Make sure that TCP connections to the port are not blocked by a firewall.".
我尝试过/验证过的内容(简短列表):
连接代码发生在活动类中,但是它在AsyncTask中。
-uses-permission android:name =“ android.permission.INTERNET”
-Azure防火墙配置为允许我的IP连接。
-Windows防火墙具有适当的规则,以允许端口1433上的传入和传出流量。
-从SQLServer Config Manager中,我启用了命名管道和TCP / IP。在IP地址选项卡上,我已启用所有功能并将TCP端口设置为1433。尝试同时使用和关闭TCP动态端口。
-已尝试使用SQL Server Browser运行和停止(另一篇文章提到这样做)。
-尝试同时使用jre7和jre8 JDBC驱动程序。
-sourceCompatibility和targetCompatibility在相应的1_7或1_8版本中设置。
-compile files('libs / sqljdbc41.jar')[或对于jre8为42]
-更加拼命并确保它们不是问题,在完全关闭Windows防火墙并允许任何IP通过Azure防火墙进行连接(起始/结束IP为0.0.0.0-255.255.255.255)之后,我也无法连接
-我可以ping&telnet到(mydbname).database.windows.net 1433(DNS和实际IP)
考虑到以上所有内容,我只能假定错误位于代码内的某个位置,但我绝对无法弄清楚错误在哪里。为了给棺材钉上钉子,应该提到的是,我能够成功查询数据库并在项目中返回值,但只能在静态,非活动类中进行。当将代码添加到实际活动类中时,几乎完全复制代码不会产生任何结果。
这是工作代码:
import java.sql.*;
public class DatabaseHelper {
public static void main(String[] args) throws Exception {
String custID = "1";
String connectionString = "jdbc:sqlserver://vet-to-go.database.windows.net:1433;database=Vet To Go DB;user=myLogin@vet-to-go;password=myPass;encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30;";
String queryString = "SELECT FirstName, LastName FROM Tbl_Customer WHERE CustomerID = " + custID;
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
Connection myConnection = DriverManager.getConnection(connectionString);
Statement myStatement = myConnection.createStatement();
ResultSet myResultSet = myStatement.executeQuery(queryString);
myResultSet.next();
String firstName = myResultSet.getString("FirstName");
String lastName = myResultSet.getString("LastName");
System.out.println(firstName);
System.out.println(lastName);
myStatement.close();
myConnection.close();
}
}
我知道其中一些代码看起来很奇怪,这只是因为我希望将其合并到另一个类中。这是我最近的尝试(正如我提到的,我已经做了一段时间了,所以我尝试了几种不同的组合)
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import java.sql.*;
public class LandingPage extends AppCompatActivity {
TextView txtFirst, txtLast;
String firstName, lastName, customerID;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_landing_page);
txtFirst = (TextView)findViewById(R.id.txtFirstName);
txtLast = (TextView)findViewById(R.id.txtLastName);
customerID = getIntent().getStringExtra("custID");
new myAsyncTask(LandingPage.this).execute();
txtFirst.setText(firstName);
txtLast.setText(lastName);
}
public class myAsyncTask extends AsyncTask<Void, Void, String> {
String connectionString = "jdbc:sqlserver://vet-to-go.database.windows.net:1433;database=Vet To Go DB;user=myLogin@vet-to-go;password=myPass;encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30;";
String queryString = "SELECT FirstName, LastName FROM Tbl_Customer WHERE CustomerID = " + customerID;
Context context;
public myAsyncTask(Context context) {
System.out.println("Async instantiated.");
this.context = context;
}
protected void onPreExecute() {
System.out.println("Pre-executing Async task.");
}
protected String doInBackground(Void... params) {
try {
System.out.println("Attempting to connect to DB...");
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
Connection con = DriverManager.getConnection(connectionString);
Statement st = con.createStatement();
ResultSet rs = st.executeQuery(queryString);
while (rs.next()) {
System.out.println("Sorting through ResultSet...");
firstName = rs.getString("FirstName");
lastName = rs.getString("LastName");
}
} catch (SQLException ex) {
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
}
return "Complete";
}
protected void onPostExecute(String result) {
if (result.equals("Complete")) {
System.out.println("Async task complete.");
}
}
}
}
运行上面的代码后,我得到“与主机vet-to-go.database.windows.net的TCP / IP连接,端口1433失败。”此行错误:
Connection con = DriverManager.getConnection(connectionString);
我不认为这是相关的,但以防万一,这是MainActivity中当前的全部内容:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etID = (EditText)findViewById(R.id.etCustID);
btnSubmit = (Button)findViewById(R.id.btnSubmit);
btnSubmit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
customerID = etID.getText().toString();
myIntent = new Intent(MainActivity.this, LandingPage.class);
myIntent.putExtra("custID", customerID);
startActivity(myIntent);
}
});
}
Android Studio 2.3
Build#AI-162.3764568,建于2017年2月24日
JRE:1.8.0_112-release-b06 amd64
JVM:JetBrains s.r.o的OpenJDK 64位服务器VM
Gradle版本3.3
目标API 22:Android 5.1
最小SDK V 21
生成工具v 25.0.0
最佳答案
首先,在Android上直接连接Azure SQL数据库不是一个好主意。通常,建议的方法是通过调用一些REST API访问数据库,这些API是在Azure上作为Web App或Mobile App创建的。
其次,许多现有的SO线程都存在与您类似的问题,一种解决方法是在Android上使用jTDS
驱动程序而不是MS SQL Server驱动程序sqljdbc
进行连接,因为sqljdbc
驱动程序似乎在Android上不完全受支持。 。作为参考,请参阅以下已解决的这些线程。
https://social.msdn.microsoft.com/forums/sqlserver/en-US/4799819a-27fd-4292-a3d8-f114207c20b2/using-the-jdbc-driver-with-android
Sql Database connect Using the JDBC Driver with android
how to connect sql server using JTDS driver in Android
希望能帮助到你。