jeudi 24 février 2011

Synchronisation entre serveur distant sql server et Android

Android fournit plusieurs options pour enregistrer les données de votre applicationvotre choix dépend de vos besoins spécifiques comme par exemple si les données doivent être privés de votre application ou accessibles à d'autres applications et combien d'espace de vos données exige.

Vos options de stockage de données sont les suivantes:
-Préférences partagés : Utiliser des données primitifs sous forme de paire clé-valeur.
-Stockage interne : Stocker des données privées sur la mémoire de l'appareil.
-Stockage externe : Stocker des données publiques sur le stockage partagé externe.
-Bases de données SQLite : Base de données embarquée.
-Connexion réseau : Stocker des données sur le web avec votre propre serveur de réseau.



Je vais vous présenter une méthode de synchronisation entre un serveur distant sql server et votre application Android via des servlets et une sérialisation JSON :

Du coté de l'application Android, on va créer 2 activités pour exporter et importer les données du serveur :

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.http.HttpConnection;
import org.apache.http.HttpEntity;
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.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;

import android.app.Activity;
import android.app.ProgressDialog;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.Toast;

public class ExporterData extends Activity implements Runnable{
ProgressDialog progressDialog;
//url du serveur distant qui contient le servlet d'exportation de données
public static final String URL_SERVER="http://www.swi*******.net/projetInsert/InsertServlet";
@Override
//au moment de la creation de l'activité
   public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.main);// mettre la vue initiale
       progressDialog = new ProgressDialog(this); // mettre un message informe l'utilisateur que les données entrain de se telecharger
       progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
       progressDialog.setMessage("Loading. Please wait...");
       progressDialog.setCancelable(false);
       progressDialog.show();
       //creer et lancer le thread d'importation des données
       Thread thread = new Thread(this);
         thread.start();
   
}
@Override
//executer le thread
public void run() {
// TODO Auto-generated method stub
try {
//exporter les données
postData();

} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//fin de thread
handler.sendEmptyMessage(0);
}
private Handler handler = new Handler() {
   @Override
   public void handleMessage(Message msg) {
    progressDialog.dismiss();
   
setResult(RESULT_OK);
finish();
   }
};
DBAdapter db;
//fonction qui verifie la connexion internet du mobile et l'etat du serveur
public boolean verifierServeur(){
try{
URL url = new URL(URL_SERVER);

 HttpURLConnection connection = (HttpURLConnection) url.openConnection();
 if (connection.getResponseCode() /100 != 2) {
 throw new IOException("Response not OK Version" + connection.getResponseCode());
 }
}
 catch(IOException e){
 return false;
 }
 return true;
}
//fonction qui serialise les données en format JSON et les envoie au serveur
public void postData() throws JSONException {
   // Create a new HttpClient and Post Header
   HttpClient httpclient = new DefaultHttpClient();
   HttpPost httppost = new HttpPost(URL_SERVER);

 db=new DBAdapter(this);
   try {
       // Add your data
    db.open();
    //requete a la BD SQLite
    Cursor c=db.getEnqueteByExport();
    if(c.getCount()==0){
   
   
    return ;
    }
    c.moveToFirst();
    JSONArray aEnq=new JSONArray();
    //serialisation des resultats de la requete
    do{

       JSONObject b=new JSONObject();
       b.put("Id_Enquete", c.getString(1));
   
       b.put("Id_User", c.getLong(5));
 
       b.put("Date_Debut",c.getString(3) );
 
       b.put("Id_Client", c.getLong(2));
     
     if(!c.isNull(4)) { b.put("Date_fin", c.getString(4));}
     else {b.put("Date_fin","null");}
       aEnq.put(b);
       db.updateEnqueteExport(c.getLong(0), 1);
    }while(c.moveToNext());
    String s= aEnq.toString()+"new";
    JSONArray aEnq_det=new JSONArray();
    c.moveToFirst();
    do{
    Cursor c1=db.getEnquete_detByEnq(c.getLong(0));
    JSONObject b=new JSONObject();
    if(c1.getCount()!=0){
   
   
   
   
    c1.moveToFirst();
    do{
    b.put("Id_Enquete_det", c1.getString(1));
   
       b.put("Id_Enquete", c.getString(1));
       b.put("Date_Enquete", c.getString(3));
       b.put("Id_Article",c1.getLong(2) );
 
       b.put("EstDisponible", c1.getInt(4));
       b.put("EstEnStock", c1.getInt(3));
       b.put("Position_yeux", c1.getString(6));
       b.put("Prix", c1.getFloat(8));
       b.put("Longueur", c1.getString(7));
       aEnq_det.put(b);
       }while(c1.moveToNext());
     }
    }while(c.moveToNext());
    s+=aEnq_det.toString();
       httppost.setEntity(new StringEntity(s));
       
       db.close();
       // Execute HTTP Post Request
       HttpResponse response = httpclient.execute(httppost);
     
 
     
   } catch (ClientProtocolException e) {
       // TODO Auto-generated catch block
   } catch (IOException e) {
       // TODO Auto-generated catch block
   }

}

}


Il vous reste l'activité  qui va recevoir les données envoyées par le serveur :

public class ImporterData extends Activity implements Runnable {

//url du servlet
public static final String URL_SERVER="http://www.swi*******.net/ProjetImport/testServlet";
DBAdapter db ;

public static  final int SUCCES=1;
public static final int ECHEC=-1;
public static  final int CONNECTION_EXCEPTION=0;
ProgressDialog progressDialog;
@Override
   public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.main);
       db = new DBAdapter(this);
   
       progressDialog = new ProgressDialog(this);
       progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
   
       progressDialog.setMessage("Loading. Please wait...");
       progressDialog.setCancelable(false);
       progressDialog.show();
       Thread thread = new Thread(this);
           thread.start();
 
}
//connecter au serveur et importer les données
public void connect(int id) throws Exception{
URL url = new URL(URL_SERVER+"?id="+id);

 HttpURLConnection connection = (HttpURLConnection) url.openConnection();
 if (connection.getResponseCode() /100 != 2) {
 Toast.makeText(this, "Response not OK Version" + connection.getResponseCode(), Toast.LENGTH_LONG);
  throw new IOException("Response not OK Version" + connection.getResponseCode());
 }

 InputStreamReader in= new InputStreamReader(connection.getInputStream());
 BufferedReader reader= new BufferedReader(in);
 StringBuffer sbf= new StringBuffer();
 String line= null;
 while((line=reader.readLine())!=null){
  sbf.append(line+ "\n");
 }
 switch(id){


 case 1: extractArticles(sbf);break;
 case 2: extractClients(sbf);break;
 case 3: extractGroupes(sbf);break;
 case 4: extractUsers(sbf);break;
 case 6: extractMag_Art(sbf);break;
 }


}
//fonction qui importe les articles
public void extractArticles(StringBuffer sbf) throws JSONException{
JSONArray jArray = new JSONArray(sbf.toString());
db.open();
     for(int i=0;i<jArray.length();i++){
             JSONObject json_data = jArray.getJSONObject(i);
           db.insertArticle(json_data.getLong("Id_Article"), json_data.getString("Designation"));
          
}
     db.close();
}
public void extractClients(StringBuffer sbf) throws JSONException{
JSONArray jArray = new JSONArray(sbf.toString());
db.open();
    for(int i=0;i<jArray.length();i++){
            JSONObject json_data = jArray.getJSONObject(i);
         db.insertCustomer(json_data.getLong("Id_Client"), json_data.getString("Identite"), json_data.getLong("Id_Groupe"));
        
}
    db.close();
}
public void extractGroupes(StringBuffer sbf) throws JSONException{
JSONArray jArray = new JSONArray(sbf.toString());
db.open();
    for(int i=0;i<jArray.length();i++){
            JSONObject json_data = jArray.getJSONObject(i);
        
db.insertGroups(json_data.getLong("Id_Groupe"), json_data.getString("Groupe"));

}
    db.close();
}
public void extractUsers(StringBuffer sbf) throws JSONException{
JSONArray jArray = new JSONArray(sbf.toString());
db.open();
   for(int i=0;i<jArray.length();i++){
           JSONObject json_data = jArray.getJSONObject(i);
        db.insertEnqueteur(json_data.getLong("Id_User"), json_data.getString("Identite"), json_data.getString("Identite"),
          json_data.getString("Login"), json_data.getString("Mpt"));
    
}
   db.close();
}
public void extractMag_Art(StringBuffer sbf) throws JSONException{
JSONArray jArray = new JSONArray(sbf.toString());
db.open();
   for(int i=0;i<jArray.length();i++){
           JSONObject json_data = jArray.getJSONObject(i);
          db.insertMagArticle(json_data.getLong("I3"), json_data.getLong("I2"));
        
}
   db.close();
}
@Override
public void run() {
// TODO Auto-generated method stub
//vider la BD du mobile
db.open();
     db.deleteAllMag_Art();
     db.deleteAllArticle();
     db.deleteAllEnqueteur();
     db.deleteAllGroup();
     db.deleteAllClient();
     db.close();
  
    try {
     //mettre a jour la BD du mobile
connect(4);
connect(3);
connect(2);
connect(1);
connect(6);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
handler.sendEmptyMessage(0);
}
private Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
     progressDialog.dismiss();
    
setResult(RESULT_OK);
finish();
    }
};

public boolean verifierServeur(){
try{
URL url = new URL(URL_SERVER+"?id="+1);

 HttpURLConnection connection = (HttpURLConnection) url.openConnection();
 if (connection.getResponseCode() /100 != 2) {
 throw new IOException("Response not OK Version" + connection.getResponseCode());
 }
}
 catch(IOException e){
 return false;
 }
 return true;
}
}

Du coté du serveur, on a utilisé deux servlets qui interrogent avec la base de données sql server distante : envoyer et recevoir les données  sous format JSON.

NB : Vous devez ajouter le jar de JSON.

Cette méthode pose des problèmes en cas d'un flux de données important, alors lsolution Webservice est la plus appropriée.





4 commentaires:

  1. Bravo Ameni =)
    Keep Shining !!!

    Meriam ZAOUALI
    Past Présidente du Club LibertySoft
    Eleve ingénieur en génie logiciel

    RépondreSupprimer
  2. je n'ai pas essayé ce code mais j'en ai vraiment besoin, j'espère réussir mon application mobile qui va être lié au serveur sql

    RépondreSupprimer
  3. bonjour Monsieur,
    je veux développer une remote pour contrôler XBMC/Kodi en android en utilisons json-rpc vous pouvez m'aider ?
    merci

    RépondreSupprimer