I'm new and am trying to connect an android application to my oracle db. My current code is throwing the error:
android.os.NetworkOnMainThreadException ...
My connection code is as follows:
public class ConnectOra {
public String driver, url, ip, bd, usr, pass;
public Connection conexion;
public ConnectOra(String ip, String bd, String usr, String pass) {
driver = "oracle.jdbc.driver.OracleDriver";
this.bd = bd;
this.usr = usr;
this.pass = pass;
url = new String("jdbc:oracle:thin:#" + ip + ":1521:" + bd);
try {
Class.forName(driver).newInstance();
conexion = DriverManager.getConnection(url, usr, pass);
// revisan el log para ver que tira....
System.out.println("Conexion a Base de Datos " + bd + " Exitosa");
} catch (Exception exc) {
System.out.println("Error al tratar de abrir la base de Datos "
+ bd + " : " + exc + "ricardo");
}
}
public Connection getConexion() {
return conexion;
}
public Connection CerrarConexion() throws SQLException {
conexion.close();
conexion = null;
return conexion;
}
Well as the error suggests, you cannot do a network connection on the main thread... So put it in a separate thread.
You have to use another thread for network tasks.
I recommend you use AsyncTask.
U should implement AsyncTask and add: to your android mainfest.
Anyway, it's a really bad practice in termns of security made a direct connection from any local client to a remote DB, that model extinguished for very good reasons years ago, in this case, in Android, if u have the apk file, u can decompress it and then decompile the java source files for get the db credentials and gain complete access to the db.
Related
I am using Unity for the first time.
I am making a app to work on Android platform.
I made a script to add to one button. The interface has a text input field to add names of a group. After writing some name and hit one button (adicionar), it should add the name in a text field (named textoGrupo). It would also enabled a second button (named seguinte), that would be disabled since the begining of the script execution. I also have another text field (textoElementoRepetido) that should have text only if the name written is repeated.
It works fine when I tested it in Unity. But when I test it on my Android device it does nothing of what's on the script.
Here is my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Data;
using Mono.Data.SqliteClient;
using TMPro;
using System.IO;
public class grupo : MonoBehaviour
{
List<string> elementos = new List<string>();
private IDbConnection connection;
private IDbCommand command;
string dbFile;
int idGrupo = 0;
public TMP_InputField input;
public TMP_Text textoGrupo;
public TMP_Text textoElementoRepetido;
public Button seguinte;
// Start is called before the first frame update
IEnumerator Start()
{
// Ligação à base de dados
string filepath = Application.persistentDataPath + "/TVdatabase.db";
if (!File.Exists(filepath))
{
// if it doesn't ->
// open StreamingAssets directory and load the db ->
WWW loadDB = new WWW("jar:file://" + Application.dataPath + "!/assets/TVdatabase.db"); // this is the path to your StreamingAssets in android
while (!loadDB.isDone)
{
yield return new WaitForSeconds(30);
} // CAREFUL here, for safety reasons you shouldn't let this while loop unattended, place a timer and error check
// then save to Application.persistentDataPath
File.WriteAllBytes(filepath, loadDB.bytes);
}
//open db connection
connection = new SqliteConnection("URI=file:" + filepath);
seguinte.interactable = false;
}
public void AdicionaElemento( )
{
if (input.text != null && input.text != "")
{
string sql;
//se ainda não existirem elementos no grupo, é criado na base de dados um grupo e o seu id é guardado
if (elementos.Count == 0)
{
command = connection.CreateCommand();
connection.Open();
sql = "INSERT INTO Grupo(idAvatar) VALUES(1);";
command.CommandText = sql;
command.ExecuteNonQuery();
sql = "SELECT MAX(idGrupo) FROM GRUPO;";
command.CommandText = sql;
IDataReader reader = command.ExecuteReader();
while (reader.Read())
{
idGrupo = reader.GetInt32(0);
}
connection.Close();
}
string elemento = input.text.ToString();
if (!elementos.Contains(item: elemento))
{
textoElementoRepetido.text = "";
command = connection.CreateCommand();
connection.Open();
sql = "INSERT INTO Elemento(nomeElemento, idGrupo) VALUES('" + elemento + "', " + idGrupo + ");";
command.CommandText = sql;
command.ExecuteNonQuery();
connection.Close();
if (elementos.Count == 0)
{
textoGrupo.text += elemento;
}
else
{
textoGrupo.text += ", " + elemento;
}
elementos.Add(elemento);
seguinte.interactable = true;
input.text = "";
}
else
{
textoElementoRepetido.text = "Essa pessoa já faz parte do teu grupo!";
}
}
else{
seguinte.interactable = false;
}
}
// Update is called once per frame
void Update()
{
}
}
I hope I wrote enough to understand the purpose of this screen. Here is what I attached to the button adicionar.
If first tried it on the onClick() event. Didn't work. So I tried it on a trigger. Same result.
I have no idea why this works on unity editor but not on my Android device.
When I click the button adicionar with nothing on text input field the script is working. So my guess is the real problem is teh connection with the database.
I missed some steps when making the database connection. I was following this. But it still does not work.
My database file is named TVbatabase.db
I solved it. So I followed the same link that is in my question (this one). I had error, didn't know why. So I downloaded the package in that post. I realised that I did not have all the necessary plugins. I did not know they where necessary. After I imported them it worked.
I'm new to android and not much aware about it. I though have been through tutorial but still didn't get any solution. How to connect Android Studio with postgressql? Step by step!
I wrote this code in my MainActitvity.java. Is this correct? Or should I write it else where?
static final String JDBC_DRIVER = "org.postgresql.Driver";
static final String DB_URL = "jdbc:postgresql://localhost:5432/user1";
// Database credentials
static final String USER = "root";
static final String PASS = "root";
public static void main(String[] args)
{
Connection conn = null;
Statement st = null;
try{
//STEP 2: Register JDBC driver
Class.forName("org.postgresql.Driver");
//STEP 3: Open a connection
System.out.println("Connecting to database...");
conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/","root","root");
//STEP 4: Execute a query
System.out.println("Creating statement...");
st = conn.createStatement();
String sql;
sql = "SELECT first, last FROM Employees";
ResultSet rs = st.executeQuery(sql);
//STEP 5: Extract data from result set
while(rs.next()){
//Retrieve by column name
String first = rs.getString("first");
String last = rs.getString("last");
//Display values
System.out.print(", First: " + first);
System.out.println(", Last: " + last);
}
//STEP 6: Clean-up environment
rs.close();
st.close();
conn.close();
}catch(SQLException se){
//Handle errors for JDBC
se.printStackTrace();
}catch(Exception e){
//Handle errors for Class.forName
e.printStackTrace();
}
finally
{
//finally block used to close resources
try{
if(st!=null)
st.close();
}catch(SQLException se2){
}// nothing we can do
try{
if(conn!=null)
conn.close();
}
catch(SQLException se){
se.printStackTrace();
}//end finally try
}
}
use 10.0.2.2 instead of localhost, it works for me.
You cannot directly use java.sql.DriverManger, Connection, etc in Android. Android support SQLite DB, if you want to use DB in android you have to go with SQLite database. For Postgres you have to develop server side application and api services which you can the call from Android
Okay, this may be obsolete but still helpful for users (it was helpful for me)
I copied your example and worked with it because I also need to get postgres running on android. And it works!
conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/","root","root");
This will result in an error because you need to enter the database name without a slash at the and, like:
conn = DriverManager.getConnection("jdbc:postgresql://domain.com:5432/databaseName", "username", "password");
Network connections (like connection to database) must be done in an AsyncTask using doInBackground(). I did it inside an activity
public class dbactivity extends AppCompatActivity { //sry code formatting just broke
String message = null;
String conmsg = null;
private class pgsqlcon extends AsyncTask<Void, Void, Void>
{
public pgsqlcon()
{
super();
}
#Override
protected Void doInBackground(Void... voids) {
Connection conn = null;
Statement st = null;
try
{
//STEP 2: Register JDBC driver
Class.forName("org.postgresql.Driver");
//STEP 3: Open a connection
System.out.println("Connecting to database...");
message = "Connecting to database...";
conn = DriverManager.getConnection("jdbc:postgresql://serverdomain.com:5432/databasename",
"dbusername", "password");
//and so on
If you need to make UI changes like setText, you must use runOnUiThread like so ():
//using quote because code formatting doesn't work anymore for me xD
private void setAsyncText(final TextView text,final String value){
runOnUiThread(new Runnable() {
#Override
public void run() {
if (value == null)
text.setText("null");
else
text.setText(value);
}
});
}
Oh yeah and last but not least, since I wrote this inside an Activiy, I have to trigger the trouble by calling my asynctask in OnCreate() of my Activity.
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dbactivity);
pgsqlcon pgcon = new pgsqlcon();
pgcon.execute();
}
}
I am not that experienced by myself so you can use this only for getting a connection at all to your postgresdb using JDBC only. Although I managed to get successful query results that way.
And again, sorry for the wrong code formatting. I did what they wanted (4 space rule etc.) and it didn't work. I hope you can read it anyway, good luck.
And if nothing of this does work, maybeeee you want to take a look at these little hints: https://jdbc.postgresql.org/documentation/head/prepare.html
(I assume you did that anyway since you have done a lot of almost correct code)
My app uses PostgreSQL as backend. Use the retrofit library for connecting to the backend. In my app backend is written in python which will make queries in the database. This will make the front-end codes more smooth and secure. And the more controls can be shifted to the back-end.
You can not connect the database with android studio directly,
you have to make connection with your application and database through api ,
and you can write your api in java, php etc.
?php
$db_connection = pg_connect("host=localhost dbname=record user=postgres password= ''");
//pg query
?>
This is your connect query api.
In My Android application I get xmpp connection initially using server_nm and 5222 port on login and done single chat message send and receive,but at time of file transfer, How I configure connection with proxy_server and 7777 port which use for file transfer?
public class XmppManager {
private static final int packetReplyTimeout = 500; // millis
private String server=server_nm;
private int port=5222;
private ConnectionConfiguration config;
private XMPPConnection connection;
String group_name,userid;
private ChatManager chatManager;
private MessageListener messageListener;
private Handler mHandler;
PacketFilter filter;
Message message;
Context context;
public static boolean IBB_ONLY = (System.getProperty("ibb") != null);//true;
protected static final String STREAM_DATA_FIELD_NAME = "stream-method";
private StreamNegotiator byteStreamTransferManager;
private StreamNegotiator inbandTransferManager;
// constructor
public XmppManager(String server, int port) {
this.server = server;
this.port = port;
}
// to initialize connection
public void init(Context c) throws XMPPException {
System.out.println(String.format(
"Initializing connection to server %1$s port %2$d", server,
port));
SmackConfiguration.setPacketReplyTimeout(50000);
config = new ConnectionConfiguration(server, port);
config.setSASLAuthenticationEnabled(false);
config.setSecurityMode(SecurityMode.disabled);
// group chat invitation
ProviderManager.getInstance().addExtensionProvider("x",
"http://jabber.org/protocol/muc#user",
new GroupChatInvitation.Provider());
// offline msgtime
ProviderManager.getInstance().addExtensionProvider("x",
"jabber:x:delay", new DelayInformationProvider());
//file transfer method
ProviderManager.getInstance().addIQProvider("query","http://jabber.org/protocol/bytestreams", new BytestreamsProvider());
ProviderManager.getInstance().addIQProvider("query","http://jabber.org/protocol/disco#items", new DiscoverItemsProvider());
ProviderManager.getInstance().addIQProvider("query","http://jabber.org/protocol/disco#info", new DiscoverInfoProvider());
ProviderManager.getInstance().addIQProvider("si","http://jabber.org/protocol/si", new StreamInitiationProvider());
ProviderManager.getInstance().addIQProvider("open","http://jabber.org/protocol/ibb", new OpenIQProvider());
ProviderManager.getInstance().addIQProvider("close","http://jabber.org/protocol/ibb", new CloseIQProvider());
ProviderManager.getInstance().addExtensionProvider("data","http://jabber.org/protocol/ibb", new DataPacketProvider());
// v-card integration
ProviderManager.getInstance().addIQProvider("vCard", "vcard-temp", new VCardProvider());
connection = new XMPPConnection(config);
connection.connect();
System.out.println("Connected: " + connection.isConnected());
chatManager = connection.getChatManager();
context = c;
Intent i = new Intent(context, MyService.class);
context.startService(i);
}
// login to xmpp server
public void performLogin(String username, String password,String resource)
throws XMPPException {
if (connection != null && connection.isConnected()) {
System.out.println("connection on presence send" + connection.isConnected() + " " + username + " " + password);
connection.login(username, password,resource);
setStatus(true, "Online");
Presence presence = new Presence(Presence.Type.available);
connection.sendPacket(presence);
}
}
//using this code I try to send file
public void sendfileafterresponse(String filenm,String filereceiverid )
{
FileTransferNegotiator.IBB_ONLY = true;
this.setServiceEnabled(connection, true);
FileTransferManager manager = new FileTransferManager(connection);
OutgoingFileTransfer transfer = manager.createOutgoingFileTransfer(filereceiverid + "#chat.bobl.us/" + filereceiverid);
File file = new File(filenm);
try {
System.out.println("file send to" + filenm + filereceiverid);
transfer.sendFile(file, "test_file");
} catch (XMPPException e) {
e.printStackTrace();
}
while(!transfer.isDone()) {
if(transfer.getStatus().equals(Status.error)) {
System.out.println("ERROR!!! " + transfer.getError());
} else if (transfer.getStatus().equals(Status.cancelled)
|| transfer.getStatus().equals(Status.refused)) {
System.out.println("Cancelled!!! " + transfer.getError());
}
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(transfer.getStatus().equals(Status.refused) || transfer.getStatus().equals(Status.error)
|| transfer.getStatus().equals(Status.cancelled)){
System.out.println("refused cancelled error " + transfer.getError());
} else {
System.out.println("Success");
}
}
}
}
If you still want to transfer files via smack directly, you basically have too options, as far as I understand the API.
1.
First you can use In Band transmission, that is enabled via
FileTransferNegotiator.IBB_ONLY = true;
This sends your file as base64 encoded message, the same way you are sending a normal message packet.
The second option is to use a streaming proxy. This one is way faster since it does not need to encode / decode the file to base64 but transmitts the data directly. Both devices connnect to the proxy server and share data on this.
To configure a streaming proxy you have to configure it on the server side and add the Providers to your client side connection (this should be done automatically on the latest asmack library).
I configured such a setup using the ejabberd service and mod_proxy65 Mod_proxy65
add to your /etc/ejabberd/ejabberd.yml, your ip adress and host should match the service you are using.
host: "proxy1.example.org"
name: "File Transfer Proxy"
ip: "200.150.100.1"
port: 7777
Then allow the firewall to communicate on this port, and you should be good to go.
However, I figured out, that the file transfer only is functional, if both clients are in the presence "available" if any of them is in another state, the sender receives "service- unavailabe" errors.
Don't rely on XMPP file transfer using aSmack/Smack as it is buly. Instead you can create a plugin which will upload files to the server and after successfully uploading the files send the absolute url of the file to the recipient so that he/she can download the file from there.
Hope this works !
I know this question is asked before also, but I want to know whether we can Connect to external database (e.g mySQL) from android device without using a webservice.
I have already build the app using webservice but now they have asked us to make it without using webservice.
Can anybody knows or give any reference about same ?
I have all the required data about the database location i.e. server name, db name etc.
Actually in my requirement I am downloading and xml using a webservice which will have all the details the connection string, database name, server name, username , password etc. but the connection is to be done on runtime.
Yes you can connect to remote database directly. I'm unsure about it's security though.
Try this:
Download MySQL JDBC
Add the .jar file in your Android project and add it as a library.
Create a class that extends AsyncTask and execute the method there.
public class connectToServer extends AsyncTask<String, String, String>{
#Override
protected String doInBackground(String... args) {
try {
connect();
} catch (Exception e) {
Log.e("Error", e.toString());
}
return null;
}
#Override
protected void onPostExecute(String file_url)
{
}
}
public void connect(){
Log.e("Android", "SQL Connection start");
Connection conn = null;
try
{
Class.forName("com.mysql.jdbc.Driver").newInstance();
String ip = "[your host server]";
String dbName = "[your dbName]";
String user = "[your userName]";
String password = "[your password]";
String connString = "jdbc:mysql://" + ip + "/" + dbName +
"";
conn = DriverManager.getConnection(connString, user, password);
Log.e("Connection", "Open");
Statement statement = conn.createStatement();
ResultSet set = statement.executeQuery("Select * from [table]");
statement.setQueryTimeout(0);
while(set.next())
{
Log.e("Data:", set.getString("[column_name]"));
}
}catch(Exception e)
{
Log.e("Error connection", e.toString());
}
}//end method
I need to make a mysql connection and get some data back. I can do this in Java using this code
try{
String username;
String password;
username = tf.getText();
password = tf2.getText();
Class.forName("com.mysql.jdbc.Driver").newInstance();
Connection con = DriverManager.getConnection("jdbc:mysql://188.181.248.30:3306/test","simon","123");
int counter = 0;
try{
Statement st = con.createStatement();
ResultSet res = st.executeQuery("SELECT * FROM KUNDER");
// System.out.println("NAVN: " + "\t" + "KREDIT: ");
while (res.next() && counter ==0) {
String i = res.getString("NAVN");
String s = res.getString("KREDIT");
System.out.println(i + "\t\t" + s);
if(username.equals(i)){
//stf3.setText("login true");
// System.out.println("username og navn passer sammen et sted");
if(password.equals(s)){
tf3.setText("login true1");
// System.out.println("pass og navn passer sammen");
counter=10;
}else{
tf3.setText("login fail");
counter =10;
}
}else{
//tf3.setText("login fail");
}
}
con.close();
}
catch (SQLException s){
tf3.setText("sql fail");
System.out.println("SQL code does not execute.");
}
But when I try to do this in Android, I get an error when trying to launch the app saying:
[2011-03-06 00:30:04 - sqlLite] Conversion to Dalvik format failed with error 1
I don't know what to do right now. I been reading around the net, but can't find anything I can get working.
Do not access MySQL from Android via JDBC. Wrap your MySQL database in a Web service, and access the Web service from Android.
You might also want to read: Why is the paradigm of "Direct Database Connection" not welcomed by Android Platform?