Pertama, diasumsikan kalian dah punya paket AMP (Apache Mysql PHP), entah itu XAMPP atau lainnya, nanti akan difungsikan sebagai WebService. Trus buat MySQL tabelnya.
CREATE TABLE `users` (
`idx` int(11) NOT NULL AUTO_INCREMENT,
`user` varchar(30) NOT NULL,
`pass` varchar(40) NOT NULL,
`email` varchar(60) NOT NULL,
`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
PRIMARY KEY (`idx`),
UNIQUE KEY `user` (`user`),
UNIQUE KEY `email` (`email`)
)
Lanjut, file index.php untuk API (Aplication Program Interface), yang akan menjadikan AMP kita jadi WebService. Untuk keperluan ini, letakkan file index.php ini di folder \xampp\httdocs\android\api\
<?php
// =============
// param2 ini biasa disimpan dalam file .php tersendiri
// =============
$DB_HOST = "localhost";
$DB_USER = "root";
$DB_PASS = "";
$DB_NAME = "silsilah";
$tb_user = "users";
// =============
// mulai routine
// =============
$conn = mysqli_connect($DB_HOST, $DB_USER, $DB_PASS, $DB_NAME) or die("Koneksi gagal");
$json = array();
$u = "";
$p = "";
$e = "";
$s1 = 0;
if(isset($_POST['u'])){
$username = $_POST['u'];
} else $s1++;
if(isset($_POST['p'])){
$password = $_POST['p'];
} else $s1++;
if(isset($_POST['e'])){
$email = $_POST['e'];
} else $s1++;
if ($s1 > 1) {
$json['status'] = 0;
$json['pesan'] = "Error 404";
echo json_encode($json);
return;
}
// =============
// ada email: Registration of new user
// =============
if(!empty($username) && !empty($password) && !empty($email)){
$hashed_password = md5($password);
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
$query = "select * from ".$tb_user." where user= '$username' OR email = '$email'";
$result = mysqli_query($conn, $query);
if (mysqli_num_rows($result) > 0){
$json['status'] = 0;
$json['pesan'] = "Gagal: username/email sudah digunakan";
} else {
$query = "insert into ".$tb_user." (user, pass, email, created_at, updated_at) values ('$username', '$hashed_password', '$email', NOW(), NOW())";
$inserted = mysqli_query($conn, $query);
if ($inserted == 1){
$json['status'] = 1;
$json['pesan'] = "Registrasi sukses";
} else {
$json['status'] = 0;
$json['pesan'] = "Gagal: tidak bisa membuat username ".$username;
}
}
} else {
$json['status'] = 0;
$json['pesan'] = "Gagal: email nggak valid";
}
}
// =============
// tanpa email: User Login
// =============
if(!empty($username) && !empty($password) && empty($email)){
$hashed_password = md5($password);
$query = "select * from ".$tb_user." where user = '$username' AND pass = '$hashed_password' Limit 1";
$result = mysqli_query($conn, $query);
if (mysqli_num_rows($result) > 0){
$json['status'] = 1;
$json['pesan'] = "Login sukses";
} else {
$json['status'] = 0;
$json['pesan'] = "Login gagal";
}
}
echo json_encode($json);
mysqli_close($conn);
?>
Lanjutkan dengan file untuk buat aplikasi Android, disini saya pake Eclipse (saya anggap kalian dah biasa bikin apk, jadi langsung file-nya saja)
Pertama, file activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#eeffee"
tools:context=".MainActivity" >
<RelativeLayout
android:id="@+id/lay_logged"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_marginLeft="@dimen/activity_margin_16"
android:layout_marginRight="@dimen/activity_margin_16"
android:visibility="invisible" >
<TextView
android:id="@+id/tv_welcome"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="@string/app_name"
android:textAppearance="?android:attr/textAppearanceMedium" />
<View
android:id="@+id/v1"
android:layout_width="wrap_content"
android:layout_height="2dp"
android:layout_below="@+id/tv_welcome"
android:background="#88aa88" >
</View>
<LinearLayout
android:id="@+id/linBlank"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/v1"
android:orientation="vertical"
android:padding="@dimen/activity_margin_8" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/login_sukses" />
<Button
android:id="@+id/btn_logout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/logout" />
</LinearLayout>
</RelativeLayout>
<TableLayout
android:id="@+id/tbl_login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_margin="@dimen/activity_margin_16"
android:background="#ddeedd"
android:padding="@dimen/activity_margin_16" >
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="@dimen/activity_margin_8"
android:text="@string/username"
android:textAppearance="?android:attr/textAppearanceMedium"
tools:ignore="RtlHardcoded" />
<EditText
android:id="@+id/username_field"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:inputType="text" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/activity_margin_8" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/password"
android:textAppearance="?android:attr/textAppearanceMedium" />
<EditText
android:id="@+id/password_field"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:inputType="textPassword" />
</TableRow>
<Button
android:id="@+id/btn_login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/login" />
<TextView
android:id="@+id/tv_pesan_ndaftar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/activity_margin_32"
android:text="@string/registration_instruction"
android:textAppearance="?android:attr/textAppearanceMedium" />
<Button
android:id="@+id/btn_register"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/activity_margin_8"
android:text="@string/register_button" />
</TableLayout>
</RelativeLayout>
Kedua file activity_regs.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#eeffee"
tools:context="com.munengan7camp.gotrah.RegsActivity" >
<LinearLayout
android:id="@+id/lin_register"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_margin="@dimen/activity_margin_16"
android:background="#00008800"
android:orientation="vertical" >
<EditText
android:id="@+id/et_username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/activity_margin_8"
android:hint="@string/username"
android:inputType="text"
android:textColor="#444444" />
<EditText
android:id="@+id/et_pass"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/activity_margin_8"
android:hint="@string/password"
android:inputType="textPassword"
android:textColor="#444444" />
<EditText
android:id="@+id/et_retype_pass"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/activity_margin_8"
android:hint="@string/re_type_pwd"
android:inputType="textPassword"
android:textColor="#444444" />
<EditText
android:id="@+id/et_email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/activity_margin_8"
android:hint="@string/email"
android:inputType="textEmailAddress"
android:textColor="#444444" />
<Button
android:id="@+id/btn_ok_register"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/activity_margin_16"
android:text="@string/register_button" />
</LinearLayout>
</RelativeLayout>
Lanjut file pendukung, string.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Registrasi Login</string>
<string name="username">Username</string>
<string name="password">Password</string>
<string name="re_type_pwd">re-type pwd</string>
<string name="email">Email</string>
<string name="login">Login</string>
<string name="logout">Logout</string>
<string name="registration_instruction">Not registered\nKlik buton to register</string>
<string name="register_button">Register now</string>
<string name="login_sukses">Login sukses</string>
<string name="gagal_konek">unable to connect to server, check internet connection</string>
</resources>
Dan ini file dimens.xml untuk spasi layout
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_margin_4">4dp</dimen>
<dimen name="activity_margin_8">8dp</dimen>
<dimen name="activity_margin_16">16dp</dimen>
<dimen name="activity_margin_32">32dp</dimen>
</resources>
Sekarang file java-nya
Pertama file MainActivity.java
package com.munengan7camp.registrasilogin;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TableLayout;
import android.widget.TextView;
import android.widget.Toast;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends Activity {
protected String enteredUsername;
String last_user = "";
TableLayout tbl_log_in;
LinearLayout linBlank;
RelativeLayout lay_logged;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
last_user = getItemShared(UtilitiLogin.shared_user_info);
tbl_log_in = (TableLayout) findViewById(R.id.tbl_login);
lay_logged = (RelativeLayout) findViewById(R.id.lay_logged);
linBlank = (LinearLayout) findViewById(R.id.linBlank);
final EditText et_username = (EditText) findViewById(R.id.username_field);
final EditText et_password = (EditText) findViewById(R.id.password_field);
Button loginButton = (Button) findViewById(R.id.btn_login);
loginButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
enteredUsername = et_username.getText().toString();
String enteredPassword = et_password.getText().toString();
if (enteredUsername.equals("") || enteredPassword.equals("")) {
Toast.makeText(MainActivity.this,
"Username / password can not zonk",
Toast.LENGTH_SHORT).show();
return;
}
POST_LoginClass asyncRequestObject = new POST_LoginClass();
asyncRequestObject.execute(UtilitiLogin.urlIndex,
enteredUsername, enteredPassword);
}
});
Button registerButton = (Button) findViewById(R.id.btn_register);
registerButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent_register = new Intent(MainActivity.this,RegsActivity.class);
startActivity(intent_register);
}
});
Button btLogout = (Button) findViewById(R.id.btn_logout);
btLogout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AlertDialog.Builder log_out = new AlertDialog.Builder(MainActivity.this);
log_out.setTitle("Log-out ?");
// OK
log_out.setPositiveButton("Yes",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
// hapus data login
SharedPreferences preferences = PreferenceManager
.getDefaultSharedPreferences(getApplicationContext());
SharedPreferences.Editor editor = preferences.edit();
editor.clear();
editor.commit();
last_user = "";
tbl_log_in.setVisibility(View.VISIBLE);
lay_logged.setVisibility(View.GONE);
}
});
// CANCEL
log_out.setNegativeButton("No",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
}
});
log_out.show();
}
});
}
protected void onResume() {
super.onResume();
last_user = getItemShared(UtilitiLogin.shared_user_info);
if (last_user == null) {
tbl_log_in.setVisibility(View.VISIBLE);
lay_logged.setVisibility(View.GONE);
} else {
logged_in();
}
}
private void saveItemShared(String item, String isi) {
SharedPreferences preferences = PreferenceManager
.getDefaultSharedPreferences(getApplicationContext());
SharedPreferences.Editor editor = preferences.edit();
editor.putString(item, isi);
editor.apply();
}
private String getItemShared(String item) {
SharedPreferences preferences = PreferenceManager
.getDefaultSharedPreferences(getApplicationContext());
String name = preferences.getString(item, null);
return name;
}
private void logged_in() {
TextView tv_log_as = (TextView) findViewById(R.id.tv_welcome);
tv_log_as.setText("Login as " + last_user);
tbl_log_in.setVisibility(View.GONE);
lay_logged.setVisibility(View.VISIBLE);
}
// ===========
// class login
// ===========
private class POST_LoginClass extends AsyncTask<String, Void, String> {
ProgressDialog pdQuery = new ProgressDialog(MainActivity.this);
@Override
protected void onPreExecute() {
super.onPreExecute();
pdQuery.setTitle("Loging in");
pdQuery.setMessage("Please wait...");
pdQuery.setCancelable(false);
pdQuery.show();
}
@Override
protected String doInBackground(String... params) {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("u", params[1]));
nameValuePairs.add(new BasicNameValuePair("p", params[2]));
String jRes = UtilitiLogin.POST_HTTP_Request(params[0],
nameValuePairs);
return jRes;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
pdQuery.dismiss();
if (result.equals("") || result == null) {
Toast.makeText(MainActivity.this, getString(R.string.gagal_konek),
Toast.LENGTH_SHORT).show();
return;
}
int status = UtilitiLogin.integerParsedJsonObject(result);
if (status == 0) {
String pesan = UtilitiLogin.stringParsedJsonObject(result);
Toast.makeText(MainActivity.this, pesan, Toast.LENGTH_LONG).show();
return;
}
if (status == 1) {
saveItemShared(UtilitiLogin.shared_user_info, enteredUsername);
last_user = enteredUsername;
logged_in();
}
}
}
// ===============
// class list_trah, kalo mo pake GET [bukan POST]
// ===============
/*
private class GET_ListClass extends AsyncTask<String, Void, String> {
ProgressDialog pdQuery = new ProgressDialog(MainActivity.this);
String url="";
@Override
protected void onPreExecute() {
super.onPreExecute();
pdQuery.setTitle("retrieving");
pdQuery.setMessage("please_wait");
pdQuery.setIndeterminate(false);
pdQuery.setCancelable(false);
pdQuery.show();
}
@Override
protected String doInBackground(String... params) {
url = params[0];
String jsonResult = UtilitiLogin.GET_HTTP_Request(url);
return jsonResult;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
pdQuery.dismiss();
if ( url.startsWith(UtilitiLogin.urlListTrah) ) {
list_trah(result);
} else {
hapus_item(result);
}
}
}
*/
}
Lanjut ke file RegsActivity.java
package com.munengan7camp.registrasilogin;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import java.util.ArrayList;
import java.util.List;
public class RegsActivity extends Activity {
protected String enteredUsername;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_regs);
final EditText username = (EditText) findViewById(R.id.et_username);
final EditText password = (EditText) findViewById(R.id.et_pass);
final EditText re_type = (EditText) findViewById(R.id.et_retype_pass);
final EditText email = (EditText) findViewById(R.id.et_email);
Button signUpButton = (Button) findViewById(R.id.btn_ok_register);
signUpButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
enteredUsername = username.getText().toString();
String enteredPassword = password.getText().toString();
String retypePassword = re_type.getText().toString();
String enteredEmail = email.getText().toString();
if (enteredUsername.equals("") || enteredPassword.equals("")
|| retypePassword.equals("") || enteredEmail.equals("")) {
Toast.makeText(RegsActivity.this,
"Username / password / email can not empty",
Toast.LENGTH_SHORT).show();
return;
}
if (!enteredPassword.equals(retypePassword)) {
Toast.makeText(RegsActivity.this,
"re-type password not match", Toast.LENGTH_SHORT)
.show();
return;
}
// request authentication with remote server
POST_RegistrasiClass asyncRequestObject = new POST_RegistrasiClass();
asyncRequestObject.execute(UtilitiLogin.urlIndex, enteredUsername,
enteredPassword, enteredEmail);
}
});
}
// ================
// class registrasi
// ================
private class POST_RegistrasiClass extends AsyncTask<String, Void, String> {
ProgressDialog pdQuery= new ProgressDialog(RegsActivity.this);
@Override
protected void onPreExecute() {
super.onPreExecute();
pdQuery.setTitle("Registering");
pdQuery.setMessage("Wait please ...");
pdQuery.setCancelable(false);
pdQuery.show();
}
@Override
protected String doInBackground(String... params) {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("u", params[1]));
nameValuePairs.add(new BasicNameValuePair("p", params[2]));
nameValuePairs.add(new BasicNameValuePair("e", params[3]));
String jRes = UtilitiLogin.POST_HTTP_Request(params[0], nameValuePairs);
return jRes;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
pdQuery.dismiss();
if (result.equals("") || result == null) {
Toast.makeText(RegsActivity.this, getString(R.string.gagal_konek), Toast.LENGTH_SHORT).show();
return;
}
int status = UtilitiLogin.integerParsedJsonObject(result);
String pesan = UtilitiLogin.stringParsedJsonObject(result);
if (status == 0) {
if (pesan == null) pesan="Kesalahan lain-lain";
Toast.makeText(RegsActivity.this, pesan, Toast.LENGTH_SHORT).show();
return;
}
if (status == 1) {
// simpan login info
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
SharedPreferences.Editor editor = preferences.edit();
editor.putString(UtilitiLogin.shared_user_info, enteredUsername);
editor.apply();
editor.commit();
onBackPressed();
return;
}
}
}
}
dan jangan lupa file utilitas pembantu. UtilitiLogin.java
package com.munengan7camp.registrasilogin;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.json.JSONException;
import org.json.JSONObject;
public class UtilitiLogin {
public static final String shared_user_info = "my_user_name"; // sesuaikan, jgn ampe bentrok ama apk lain
public static final String urlServer = "http://10.0.2.2/android/api/"; // sesuaikan ama (X)AMP ente
public static final String urlIndex = urlServer + "index.php";
public static StringBuilder inputStreamToString(InputStream is) {
String rLine = "";
StringBuilder answer = new StringBuilder();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
try {
while ((rLine = rd.readLine()) != null) {
answer.append(rLine);
}
} catch (IOException e) {
e.printStackTrace();
}
return answer;
}
public static int integerParsedJsonObject(String result) {
JSONObject resultObject = null;
int returnedResult = 0;
try {
resultObject = new JSONObject(result);
returnedResult = resultObject.getInt("status");
} catch (JSONException e) {
e.printStackTrace();
}
return returnedResult;
}
public static String stringParsedJsonObject(String result) {
JSONObject resultObject = null;
String returnedResult = "";
try {
resultObject = new JSONObject(result);
returnedResult = resultObject.getString("pesan");
} catch (JSONException e) {
e.printStackTrace();
}
return returnedResult;
}
public static String POST_HTTP_Request(String url, List<? extends NameValuePair> params) {
HttpParams httpParameters = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParameters, 10000);
HttpConnectionParams.setSoTimeout(httpParameters, 10000);
HttpClient httpClient = new DefaultHttpClient(httpParameters);
HttpPost httpPost = new HttpPost(url);
String jsonResult = "";
try {
httpPost.setEntity(new UrlEncodedFormEntity(params));
HttpResponse response = httpClient.execute(httpPost);
jsonResult = inputStreamToString(
response.getEntity().getContent()).toString();
System.out.println("Returned Json object "+ jsonResult.toString());
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return jsonResult;
}
/*
public static String GET_HTTP_Request(String params) {
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(params);
String jsonResult = "";
try {
HttpResponse response = httpClient.execute(httpGet);
jsonResult = inputStreamToString(
response.getEntity().getContent()).toString();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return jsonResult;
}
*/
}
Jangan lupa, tambahkan permission.INTERNET di Manifest, ini lengkapnya file AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.munengan7camp.registrasilogin"
android:versionCode="1"
android:versionName="1.0"
android:installLocation="auto" >
<uses-permission android:name="android.permission.INTERNET"/>
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="14" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".RegsActivity" >
</activity>
</application>
</manifest>
dan, itu ajah. Kalo mo donlod file .zip (tanpa password) dari 4shared ini link-nya, dan selamat mencoba moga suskes... amin
oh ya, ditunggu komennya
Halo gan blognya sudah saya follow,,,dotunggu follow baliknya
ReplyDeletedah ane folbek as dwi.xxxxxx
DeleteArtine kudu Instal Delphi 7 dulu ya mas ....\
ReplyDeleteora yo .....
Deleteabis download ma instal my sql terus gmn.... ??
ReplyDeletesuruh bangun 100 rumah insyaallah bisa, tapi ngene iki aku gak dong, hehehee...