اتصال به SQLServer در اندروید(بخش سوم)
در آموزش های قبلی در مورد نحوه ایجاد دیتابیس در هاست و نوشتن اسکریپت های php برای ذخیره داده ها در SQLServer آشنا شدیم. در این پست و در آخرین جلسه آموزشی از این مبحث ، قرار است نحوه برنامه نویسی اندروید برای اتصال به دیتابیس SQLServer را برای دوستان عزیز ارائه کنیم. اگر در زمینه ایجاد دیتابیس و کار با اسکریپت های php برای ذخیره داده ها در SQLServer از اطلاعات کافی یا ناقصی برخوردارید ابتدا پست های قبلی مرتبط با این موضوع را بخوانید و سپس وارد این مبحث شوید . برای شروع کار بهتر است مباحث قبلی مرتبط با این موضوع را ذهن خود مرور کنید ، همانطور که پیشتر بیان گردید برنامه یا اپلیکیشن اندروید ما قرار است متغیرهای name- familyname- phonenumber- email را از کاربر گرفته و به url مورد نظر ما که اسکریپت های php در آن قرار دارد به روش post ارسال کند. در سمت سرور نیز اطلاعات از کلاینت گرفته می شود و در دیتابیس مورد نظر ما ذخیره شود.
اگر در داخل برنامه اکلیپس یا اندروید استودیو قرار دارید پروژه جدیدی را ایجاد کنید
اکلیپس :File ⇒ New Android ⇒ Application Project
اندروید استودیو :File ⇒ New ⇒ New Project
اما اگر هنوز برنامه خود را باز نکرده اید یکی از برنامه های فوق را باز نموده و بعد از تعیین مشخصات(نامگذاری) ، تعیین حداقل sdk و نوع اکتیویتی (blank یا Empty) ، نام اکتیویتی ابتدایی و اصلی خود را همان MainActivity قرار دهید. بعد از لود کامل برنامه ، در مسیر res ⇒layout لایه متناظر اکتیوتی اصلی یعنی activity_main را پیدا نمود و کدهای مندرج و پیش فرض آن را پاک کرده و کدهای xml زیر را به آن اضافه کنید:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:layout_width="fill_parent"
android:layout_height="40dp"
android:id="@+id/editText"
android:hint="youname"
android:textSize="16dp"
android:gravity="center"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="159dp" />
<EditText
android:layout_width="fill_parent"
android:layout_height="40dp"
android:id="@+id/editText1"
android:hint="youfamilyname"
android:textSize="16dp"
android:gravity="center"
android:layout_below="@+id/editText"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="35dp" />
<EditText
android:layout_width="fill_parent"
android:layout_height="40dp"
android:id="@+id/editText2"
android:hint="phonenumber"
android:textSize="16dp"
android:gravity="center"
android:layout_below="@+id/editText1"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="35dp" />
<EditText
android:layout_width="fill_parent"
android:layout_height="40dp"
android:id="@+id/editText3"
android:hint="yourEmail"
android:textSize="16dp"
android:gravity="center"
android:layout_below="@+id/editText2"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="35dp" />
<Button
android:layout_width="fill_parent"
android:layout_height="40dp"
android:text="send"
android:gravity="center"
android:textSize="15dp"
android:id="@+id/btnsend"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="73dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="connect and Save data in Sqlserver "
android:textSize="20dp"
android:id="@+id/textView"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="77dp"
android:textColor="#0814f5" />
</RelativeLayout>
در لایوت فوق ما چهار edittex و یک button قرار داده ایم که کاربر مشخصات چهارگانه مذکور را در آن نوشته و با کلیک بر روی دکمه باتن اطلاعات را به سرور ارسال خواهد کرد. در ادامه به سراغ کلاس MainActivity رفته و کدهای زیر را در به آن اضافه می کنیم.
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.EditText;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Iterator;
import javax.net.ssl.HttpsURLConnection;
public class MainActivity extends AppCompatActivity {
EditText name, familyname, phonenumber, email;
public static String Name= null;
public static String Familyname= null;
public static String PhoneNumber= null;
public static String Email= null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
name = (EditText) findViewById(R.id.editText);
familyname = (EditText) findViewById(R.id.editText1);
phonenumber = (EditText) findViewById(R.id.editText2);
email = (EditText) findViewById(R.id.editText3);
Button btnsend = (Button) findViewById(R.id.btnsend);
btnsend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Name = name.getText().toString();
Familyname =familyname.getText().toString();
PhoneNumber =phonenumber.getText().toString();
Email =email.getText().toString();
new PostData().execute();
}
});
}
public class PostData extends AsyncTask<String, Void, String> {
Context context;
protected void onPreExecute() {
}
protected String doInBackground(String... arg0) {
try {
URL url = new URL("http://psrd.ir/app/sqlpost.php");
JSONObject postDataParams = new JSONObject();
postDataParams.put("name", Name);
postDataParams.put("familyname", Familyname);
postDataParams.put("phonenumber",PhoneNumber);
postDataParams.put("email", Email);
Log.e("params", postDataParams.toString());
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(15000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"));
writer.write(getPostDataString(postDataParams));
writer.flush();
writer.close();
os.close();
int responseCode = conn.getResponseCode();
if (responseCode == HttpsURLConnection.HTTP_OK) {
BufferedReader in = new BufferedReader(new
InputStreamReader(
conn.getInputStream()));
StringBuffer sb = new StringBuffer("");
String line = "";
while ((line = in.readLine()) != null) {
sb.append(line);
break;
}
in.close();
return sb.toString();
} else {
return new String("false : " + responseCode);
}
} catch (Exception e) {
return new String("Exception: " + e.getMessage());
}
}
@Override
protected void onPostExecute(String result) {
AlertDialog.Builder alert = new AlertDialog.Builder(MainActivity.this);
alert.setMessage(result );
alert.setPositiveButton("ok",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
dialog.dismiss();
}
});
alert.show();
}
public String getPostDataString(JSONObject params) throws Exception {
StringBuilder result = new StringBuilder();
boolean first = true;
Iterator<String> itr = params.keys();
while (itr.hasNext()) {
String key = itr.next();
Object value = params.get(key);
if (first)
first = false;
else
result.append("&");
result.append(URLEncoder.encode(key, "UTF-8"));
result.append("=");
result.append(URLEncoder.encode(value.toString(), "UTF-8"));
}
return result.toString();
}
}
}
همانطور که می بینید ابتدا متغیرهایی را به منظور دسترسی در کلاس دیگر بصورت public static از نوع String تعریف کرده ام و در درون کلاس مذکور ابتدا لایوت مورد نظر را برای کلاس مشخص کرده و سپس ابزارهای موجود در آن لایوت را با فراخوانی id آنها و سپس نامگذاری اختیاری هریک از آنها ، برای کلاس تعریف نموده ایم. بعد از تعریف ابزارها ، برای برنامه چنین تعیین کرده ایم که در صورت کلیک کردن بر روی button value فیلد های متنی در edittext ها تبدیل به نوع string شده و در متغیرهای کلی ما یعنی Name,FamilyName, PhoneNumber , Email ذخیره شوند.
public class MainActivity extends AppCompatActivity {
EditText name, familyname, phonenumber, email;
public static String Name= null;
public static String Familyname= null;
public static String PhoneNumber= null;
public static String Email= null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
name = (EditText) findViewById(R.id.editText);
familyname = (EditText) findViewById(R.id.editText1);
phonenumber = (EditText) findViewById(R.id.editText2);
email = (EditText) findViewById(R.id.editText3);
Button btnsend = (Button) findViewById(R.id.btnsend);
btnsend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Name = name.getText().toString();
Familyname =familyname.getText().toString();
PhoneNumber =phonenumber.getText().toString();
Email =email.getText().toString();
new PostData().execute();
}
});
}
کلاس دیگر ما با عنوان PostData بصورت کلاس درونی در داخل کلاس MainActivty تعریف شده است. در این کلاس ما از روش Asynctasc بهره برده ایم.از این رو لازم است متدهای آن نیز باید implement گردد . در این کلاس asynctask دارای سه متد به شرح زیر می باشد که در
1- ()onPreExecute اشاره به متدی است که تعیین می کند قبل انجام عملیات اصلی در پس زمینه برنامه، چه عملیاتی صورت پذیرد. همانطور که می بینید در این متد هیچ کدی نوشته نشده است. البته می توان در این متد از ابزارهایی همچون progress bar استفاده کرد که نشان دهنده شروع عملیات و تداوم آن می باشد. سینتکس آن به شرح زیر می باشد.
protected void onPreExecute() {
}
2- doInBackground
در این متد همانطور که از نامش پیداست عملیات اصلی یعنی فراخوانی کلاس JsonObject (کلاسی كه امکان خواندن و نوشتن و پارس كردن آن را براي ماشينها فراهم می سازد) ، خواندن آدرس(Url) ، کانکت شدن به آن تعیین مدت زمان وقفه برای خواندن داده ها ، تعیین متد زمان اتصالی در صورت پیش آمدن مشکل در اتصال به سرور، تعیین متد ارسال داده (که به روش post می باشد) ، فراخوانی کانکشن برای رایت کردن در استریم ،نوشتن داده های پست شده به بافر، inputStream و outputStream ، و دریافت کد response و برگرداندن آن به نوع String که متد آن در این کلاس نوشته است. و بطور کلی چگونگی و کیفیت نوع انجام عملیات در این متد صورت می گیرد.
protected String doInBackground(String... arg0) {
try {
URL url = new URL("http://psrd.ir/fixurl/sqlpost.php");
JSONObject postDataParams = new JSONObject();
postDataParams.put("name", Name);
postDataParams.put("familyname", Familyname);
postDataParams.put("phonenumber",PhoneNumber);
postDataParams.put("email", Email);
Log.e("params", postDataParams.toString());
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(15000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"));
writer.write(getPostDataString(postDataParams));
writer.flush();
writer.close();
os.close();
int responseCode = conn.getResponseCode();
if (responseCode == HttpsURLConnection.HTTP_OK) {
BufferedReader in = new BufferedReader(new
InputStreamReader(
conn.getInputStream()));
StringBuffer sb = new StringBuffer("");
String line = "";
while ((line = in.readLine()) != null) {
sb.append(line);
break;
}
in.close();
return sb.toString();
} else {
return new String("false : " + responseCode);
}
} catch (Exception e) {
return new String("Exception: " + e.getMessage());
}
}
3-onPostExecute
این مرحله نیز از زمان اتمام عملیات اصلی شروع می شود . یعنی برنامه نویس در این متد تعیین می کند که بعد از عملیات اصلی که در این مثال پست داده ها به سرور و گرفتن respons از سرور است چه واکنشی از طرف برنامه صادر شود. که در این مثال نشان دادن نتیجه response در قالب یک آلرت دیالوگ است.
@Override
protected void onPostExecute(String result) {
AlertDialog.Builder alert = new AlertDialog.Builder(MainActivity.this);
alert.setMessage(result );
alert.setPositiveButton("ok",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
dialog.dismiss();
}
});
alert.show();
}
و در نهایت با افزودن premission زیر به AndroidManifest.xml مجوز دسترسی اپلیکیشن را به اینترنت را تعریف می کنیم.توجه داشته باشد که در صورت کپی کردن کدها نام پکیج خودرا با پکیج ارائه شده در مثال مقایسه کنید و پکیج پروژه خود را در آن لحاظ کنید.
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.site.psrd.connectsqlserver"> <uses-permission android:name="android.permission.INTERNET"></uses-permission> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity" android:label="@string/app_name" android:theme="@style/AppTheme.NoActionBar"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
حال پروژه را اجرا کرده و از آن در آموزش هر چه بیشتر خود استفاده کنید. اگر مشکلی در اجرای کدها وجود دارد یا سوال مشخصی از نویسنده سایت دارید سوالات خود را در قسمت دیدگاه ها بیان کنید.
کپی برداری از محتوای سایت psrd، ممنوع بوده و پیگرد قانونی دارد. (تنها استفاده شخصی کاربران ، مجاز است) (کپی برداری توسط سایر وب سایت ها غیرقانونی بوده و در صورت رویت به ستادسازماندهی اطلاع داده خواهد شد.
11 دیدگاه
حامد قنبری · دسامبر 14, 2017 در 6:34 ق.ظ
مشکل از thread است. یعنی اینکه که شما نیاز دارید برای انجام عملیات جدید یک ترد فرعی تعریف کنید
سعید غفاری · دسامبر 14, 2017 در 10:36 ق.ظ
سلام بنده هم با زدن دکمه send با یک کد html مواجه میشم و با زدن دوباره دکمه با ارور false:400 مواجه میشم در سمت سرور ارتباط با دیتابیسم رو چک کردم درسته
حامد قنبری · دسامبر 14, 2017 در 1:11 ب.ظ
مشکل از کدنویسی است که برای سرور قابل پردازش نیست. البته کوکی های مرورگرتان را هم پاک کنید. اگه مشکلت حل نشد کدهاتو بفرست علت خطاشو بهت بگم
سعید غفاری · دسامبر 16, 2017 در 6:20 ق.ظ
package saeed.test.www.myapplication;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.EditText;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Iterator;
import javax.net.ssl.HttpsURLConnection;
public class MainActivity extends AppCompatActivity {
EditText name, familyname, phonenumber, email;
public static String Name= null;
public static String Familyname= null;
public static String PhoneNumber= null;
public static String Email= null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
name = (EditText) findViewById(R.id.editText);
familyname = (EditText) findViewById(R.id.editText1);
phonenumber = (EditText) findViewById(R.id.editText2);
email = (EditText) findViewById(R.id.editText3);
Button btnsend = (Button) findViewById(R.id.btnsend);
btnsend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Name = name.getText().toString();
Familyname =familyname.getText().toString();
PhoneNumber =phonenumber.getText().toString();
Email =email.getText().toString();
new PostData().execute();
}
});
}
public class PostData extends AsyncTask {
Context context;
protected void onPreExecute() {
}
protected String doInBackground(String… arg0) {
try {
URL url = new URL(“http://databasetest.gigfa.com/name.php”);
JSONObject postDataParams = new JSONObject();
postDataParams.put(“name”, Name);
postDataParams.put(“familyname”, Familyname);
postDataParams.put(“phonenumber”,PhoneNumber);
postDataParams.put(“email”, Email);
Log.e(“params”, postDataParams.toString());
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(15000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod(“POST”);
conn.setDoInput(true);
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, “UTF-8”));
writer.write(getPostDataString(postDataParams));
writer.flush();
writer.close();
os.close();
int responseCode = conn.getResponseCode();
if (responseCode == HttpsURLConnection.HTTP_OK) {
BufferedReader in = new BufferedReader(new
InputStreamReader(
conn.getInputStream()));
StringBuffer sb = new StringBuffer(“”);
String line = “”;
while ((line = in.readLine()) != null) {
sb.append(line);
break;
}
in.close();
return sb.toString();
} else {
return new String(“false : ” + responseCode);
}
} catch (Exception e) {
return new String(“Exception: ” + e.getMessage());
}
}
@Override
protected void onPostExecute(String result) {
AlertDialog.Builder alert = new AlertDialog.Builder(MainActivity.this);
alert.setMessage(result );
alert.setPositiveButton(“ok”,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
dialog.dismiss();
}
});
alert.show();
}
public String getPostDataString(JSONObject params) throws Exception {
StringBuilder result = new StringBuilder();
boolean first = true;
Iterator itr = params.keys();
while (itr.hasNext()) {
String key = itr.next();
Object value = params.get(key);
if (first)
first = false;
else
result.append(“&”);
result.append(URLEncoder.encode(key, “UTF-8”));
result.append(“=”);
result.append(URLEncoder.encode(value.toString(), “UTF-8”));
}
return result.toString();
}
}
}
سعید غفاری · دسامبر 16, 2017 در 6:23 ق.ظ
البته قبل از اجرا این الرت رو هم میده
All packages are not available for download! The following packages are not available:
– Package id platforms;android-23
ولی وقتی اوکی رو میزنم برنامه ران میشه
حامد قنبری · دسامبر 16, 2017 در 6:35 ق.ظ
مجوز اتصال به اینترنت را از قسمت androidmanfest کنترل کن .
Android Studio > File > Settings > System Settings > HTTP Proxy پروکسی خودتو تنظیم کن
اگه مشکلت حل نشد : مشکل می تونه از کندی اینترنت یا sdk هم باشه
سعید غفاری · دسامبر 16, 2017 در 7:24 ق.ظ
امکان داره به خاطر محدودیت های گوگل برای ایران باشه ؟ من هیچ فیلتر شکنی ستفاده نکردم و تنظیمات پروکسیم هم روی no proxy هست
آقای قنبری من خیلی برام مهمه از این کد جواب بگیرم میدونم دارم اذیتتون میکنم ولی واقعا ممنون میشم تا گام آخر راهنماییم کنید این شماره تلگرام منه
09193480263 واقعا لطف بزرگی میکنید اگه یه پیام تو تلگرام به بنده بدید تا من بتونم تصاویر رو خدمتتون بفرستم
مهتاب · ژانویه 11, 2018 در 9:45 ب.ظ
سلام وقت بخیر
ببخشید آقا من کد رو زدم اما برنامه تا بازش میکنم بسته میشه کد php هم نوشتم درسته اما برنامه سریع بسته میشه
یه لطفی میکنین سورسشو بذارین
حامد قنبری · ژانویه 18, 2018 در 11:58 ق.ظ
اگر از هاست رایگان استفاده می کنید برخی از این هاست ها اجازه اجرای request ها را برای ذخیره داده ها در دیتابیس SqlServer vh نمی ده . بنابراین یک هاست مطمئن پیدا کنید. یا از هاست های پولی استفاده کنید.
علی · جولای 28, 2018 در 10:20 ق.ظ
سلام من سورس رو زدم ولی این پیغام رو میده:
Exception : Can’t create handler inside thread that has not called lopper.prepre
و از tread فرعی هم استفاده کردم لطفا راهنمای کنید ممنون.
حامد قنبری · آگوست 24, 2018 در 1:01 ب.ظ
شما باید بسیاری از توابع دیگر که با UI سروکار دارد را از داخل thread یا موضوع اصلی فراخوانی کنید.