‏הצגת רשומות עם תוויות api. הצג את כל הרשומות
‏הצגת רשומות עם תוויות api. הצג את כל הרשומות

יום שישי, 12 באפריל 2013

Google Maps Android



מפות רבותי, מפות, אז אחרי ש Google עשתה את כל העבודה כשמיפתה את העולם ופתחה אותו לכל מי שרק חופץ, העסק נהפך להרבה יותר פשוט, אם תשאלו אותי לפני ש Google החליטה לבצע כזה צעד נועז בתור מפתח לא חשבתי שבכלל תהיה לי היכולת להשתמש במערכות מיפוי, העסק תמיד היה נראה לי מסובך ומצריך משאבים רבים,  Google החליטה לתת השירות באופן חופשי עבור משתמשי Android ולאפשר למפתחים לשלב שירותי מיפוי באפליקציות שלהם ללא תשלום, ובשילוב ה Gps שבמכשירים ניתן לפתח אפליקציות מיקום מתקדמות.

במאמר זה אני יעבור על תהליך ההתממשקות ושלב כתיבת האפליקציה ב Android.

שימו לב! - המאמר עובר על תהליך ההתממשקות בגרסת  Google Maps Api 2 בשילוב גרסת Api 10 של Android.


התממשקות לשירותי Google

תחילה יש להירשם ל Google (מי שעוד לא הספיק) יש להיכנס לאתר API Console ואח"כ לבחור את ה Api המתאים ברשימת ה Services.



לאחר מכן  נגדיר את המפתח עבור האפליקציה, נלחץ על Create New Android Key:


במקרה של עבודה של Debug ניתן להכניס את המפתח ה Default ולהוסיף את שם ה Package שלנו כפי שניתן לראות בדוגמה:

45:B5:E4:6F:36:AD:0A:98:94:B4:02:66:2B:12:17:F2:56:26:A0:E0;com.example

במקרה של Release צריך לייצר מפתח חדש בעזרת הכלי Keytool, את מחרוזת ה SHA1 נטען בתור המפתח ולאחר מכן נרשום אותו ב Manifest כפי שמוצג בהמשך.

יצירת פרויקט:

לפני שניצור פרוייקט חדש חשוב לוודא ש Google Services Api מותקן כחלק מ Android Api 10, בנוסף יש להתקין את הדוגמאות עבור ה SDK.




ניצור פרוייקט חדש ב Eclipse של Android,   ונשנה את ה Android Build Target ל Google Api, נוסיף פרויקט נוסף  ב Workspace שנקרא google_play_services_lib  הוא נמצא בתיקיית ה Extra של ה SDK ונוסיף אותו ב Library בפרויקט כפי שניתן לראות בדוגמה:



קוד:

הקוד עצמו יחסית פשוט , ניצור מחלקה שיורשת FragmentActivity  ונחבר Interface מסוג LocationListener, נממש מספר פונקציות ונגדיר את ה Service Provider ע"פ החומרה הקיימת במכשיר על מנת לקבל את המיקום, נסמן את עצמנו במפה ונדאג לעדכן את המיקום בכל פרק זמן או מרחק שעברנו.

Activity

package com.example.urban;

import com.google.android.gms.maps.*;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;

import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.content.Context;
import android.graphics.Color;
import android.view.Menu;
import android.view.View;
import android.widget.Toast;
import android.support.v4.app.FragmentActivity;


public class GoogleMapActivity2 extends FragmentActivity implements LocationListener {

private GoogleMap mymap;

   private LocationManager locationManager;
   private String provider;
   private Marker locationMarker;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_google_map_activity2);

set_titlecolor();

//get map component from activity
   mymap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();
   //map.setMyLocationEnabled(true);
 
   //set location manager and start active and checking availability of location service
   LocationManager service = (LocationManager) getSystemService(LOCATION_SERVICE);
     
   //check for GPS
   boolean enabledGPS = service
                .isProviderEnabled(LocationManager.GPS_PROVIDER);
   //check for WIFI
   boolean enabledWiFi = service
                .isProviderEnabled(LocationManager.NETWORK_PROVIDER);

       //Check if GPS enable throw error
        if (!enabledGPS) {
            Toast.makeText(this, "GPS signal not found", Toast.LENGTH_LONG).show();
        }

       Location location = get_location();

        // Initialize the location fields
        if (location != null) {
            Toast.makeText(this, "Selected Provider " + provider,
                    Toast.LENGTH_SHORT).show();
            onLocationChanged(location);
         
        }

}

private void set_titlecolor()
{
                //just for fun change title color
View title = getWindow().findViewById(android.R.id.title);
View titleBar = (View) title.getParent();
titleBar.setBackgroundColor(Color.argb(100, 58, 58, 58));
}

private Location get_location()
{
//getting the location manager
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
       //define new Criteria for location service
       Criteria criteria = new Criteria();
       //request accuracy fine => GPS provider
       criteria.setAccuracy(Criteria.ACCURACY_FINE);
   
       provider = locationManager.getBestProvider(criteria, false);
       Location location = locationManager.getLastKnownLocation(provider);
       return location;
}

@Override
    protected void onResume() {
        super.onResume();
        //request to update location every 200 millisecond, and every 1 meter
        locationManager.requestLocationUpdates(provider,200, 1, this);
    }

    /* Remove the locationlistener updates when Activity is paused */
    @Override
    protected void onPause() {
        super.onPause();
        locationManager.removeUpdates(this);
    }

@Override
   public void onLocationChanged(Location location) {
       double lat =  location.getLatitude();
       double lng = location.getLongitude();
   
       Toast.makeText(this, "Location " + lat+","+lng,
               Toast.LENGTH_LONG).show();
     
       LatLng coordinate = new LatLng(lat, lng);
       Toast.makeText(this, "Location " + coordinate.latitude+","+coordinate.longitude,
               Toast.LENGTH_LONG).show();
     
       //remove the marker if exists
       if(locationMarker != null)
        locationMarker.remove();
     
       //add marker to map
       locationMarker = mymap.addMarker(new MarkerOptions()
       .position(coordinate)
       .title("Are You Spy On Me?")
       .snippet("don't expose your position!")
       .icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_launcher)));
     
   
       //going to update the camera with the new coordinates
       CameraUpdate center=
                    CameraUpdateFactory.newLatLng(new LatLng(coordinate.latitude,
                    coordinate.longitude));
                 //set camera zoom
CameraUpdate zoom=CameraUpdateFactory.zoomTo(17);

//move camera to location
mymap.moveCamera(center);
mymap.animateCamera(zoom);
   }

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.google_map_activity2, menu);
return true;
}


@Override
public void onProviderDisabled(String arg0) {
  Toast.makeText(this, "Enabled new provider " + provider,
               Toast.LENGTH_SHORT).show();

}


@Override
public void onProviderEnabled(String arg0) {
Toast.makeText(this, "Disabled provider " + provider,
               Toast.LENGTH_SHORT).show();

}


@Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
// TODO Auto-generated method stub

}

}

Layout

<fragment xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:map="http://schemas.android.com/apk/res-auto"
  android:id="@+id/map"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  class="com.google.android.gms.maps.SupportMapFragment"
  map:cameraTilt="30"
  map:cameraZoom="13"
  map:mapType="normal"
  map:uiCompass="false"
  map:uiRotateGestures="true"
  map:uiScrollGestures="true"
  map:uiTiltGestures="true"
  map:uiZoomControls="false"
  map:uiZoomGestures="true"/>

Manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.urban"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="10"
        android:targetSdkVersion="10" />

    <uses-feature
        android:glEsVersion="0x00020000"
        android:required="true" />

    <permission
        android:name="com.example.urban.permission.MAPS_RECEIVE"
        android:protectionLevel="signature" />

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="com.example.urban.permission.MAPS_RECEIVE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <meta-data
            android:name="com.google.android.maps.v2.API_KEY"
            android:value="your google api key!" />

        <uses-library
            android:name="com.google.android.maps"
            android:required="true" />

        <activity
            android:name="com.example.urban.GoogleMapActivity2"
            android:label="Google Maps Api 2" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


תוצאה סופית:




סיכום:

עכשיו העולם נראה קטן מתמיד ובעזרת שירותי Google העסק נהפך לפשוט יותר ולא פחות חשוב בחינם, אני לא יודע כמה זמן Google יחליטו להשאיר את השירות חינם עבור משתמשי Android אבל כנראה שכבר לא נלך לאיבוד.

תפסו כיוון!

יום שני, 12 בספטמבר 2011

Php Soap Server and .NET Client

Webservices תמיד עניינו אותי ולכן חיפשתי משהו נחמד על מנת שתוכלו להכיר אותם טוב יותר, קיימת תחרות רבה בין 2 השיטות המובילות בתחום, שיטת ה REST הנפוצה במערכות Linux , כמו שראינו במאמרים בעבר , שם מרבית העבודה מתבצעת עם REST , ולכן העבודה היא הרבה יותר קשה לניתוח, כל חברה יכולה לממש את התתמשקות בצורה אישית ללא סטנדרט מסויים ובאחריות המשתמש לנתח את הנתונים בעצמו.
 השיטה השנייה Simple Object Access  Protocol - Soap , מוגדרת כסטנדרט ועל מנת להשתמש בו יש לעמוד בחוקים שלה, מיקרוספט אימצו את השיטה ומבחינתה זאת השיטה הטובה ביותר לפיתוח בפלטפורמות Windows , אני באמת לא יודע מה יותר טוב, עדיין REST פופלרי מאוד אבל Soap מומלץ לעבודה ע"י W3C העולמית שפיתחה עבורו תקן WSDL - Web Services Description Language  , לכן זה נראה לי ויכוח שכנראה אין בו מנצחים ומפסדים וצריכים להכיר את 2 השיטות.

  חשוב מאוד! המאמר הזה מתייחס לעבודה עם Soap בסביבת Linux ונוסה על מערכת הפעלה Fedora. 

 תשתית:

תחילה יש להבין שעבודה עם Soap בסביבת Linux מצריכה Php אבל לא סתם אלא Php 5.0 ומעלה , התמיכה המלאה ב Soap קיימת בגרסה 5 בלבד, גרסאות נמוכות יותר מצריכות עבודה מול כלים של צד שלישי , בקיצור סיפור מהתחת לכן לא מומלץ לשלב Soap במערכות קיימות עם Php נמוך מגרסה 5, וכמובן שרת Apache. יש להתקין את המחלקות של ה Soap ב Php

#: yum install php-soap

* יש להפעיל את ה Apache מחדש,  ולגשת לדף הבדיקות  phpinfo ולראות אם נוספו השורות הבאות:
soap
Soap Client enabled
Soap Server enabled
DirectiveLocal ValueMaster Value
soap.wsdl_cache11
soap.wsdl_cache_dir/tmp/tmp
soap.wsdl_cache_enabled11
soap.wsdl_cache_limit55
soap.wsdl_cache_ttl8640086400

אחרי שהכנו את ה Server נתחיל לרשום את הקוד, כאן העסק מתחלק ל 2 חלקים, חלק הראשון הוא המימוש של הפונקציות והפרמטרים, במקרה הזה נכתוב קובץ עם סיומת Php , בו נכתוב את הקוד עם כמה תוספות, החלק השני הוא החשיפה של ה Webservice בעזרת קובץ WSDL בפורמט Xml.

 נעבור בקצרה על מבנה הקובץ ה Wsdl , ניתן לקבל מידע רחב בנושא בלינק הבא:


  • לפי ה Element אפשר לראות שהפונקציה שחשופה לנו היא HelloWorld , מתחת שם הפונקציה ניתן לראות שיש לה "ילדים" שהם הפרמטרים שהיא מקבלת ומחזירה ומה הסוג שלהם.
  • תגיות PortType פעולות מופשטות להודעות נכנסות ויוצאות.
  • תגיות ה Message מייצגות מידע שמועבר, מאוד חשובים לשלבים הלוגיים של ה Webservice
  • תגיות ה Binding בעצם מייצגות את הפרוטוקול את מבנה ה Data שהוגדר ע"י PortType ספציפי.
  • תגית ה Port מייצגת איזה Port קצה.
  • תגית ה Service מייצגת סדרה של Ports שקשורים ל Service.


מבנה קובץ ה Php הוא מאוד פשוט, יש הצהרה תחילה על אובייקט Server$ שמסוג SoapServer , בשלב ההצהרה נעמיס את שם הקובץ ה WSDL לכן ממולץ שהקבצים ישבו באותה תקייה, לאחר מכן נוסיף לאובייקט את הפונקציה אותה אנו מעוניינים לחשוף ולאחר מכן נחבר את ה Handle על מנת שהיא תופעל. אין יותר מידי מה לפרט על הפונקציה בגדול אנחנו צריכים להוציא את הפרמטר שנשלח ע"י שימוש במערך וע"פ השם שניתן בקובץ ה Wsdl.

 

טיפ להתחלה:
 מומלץ לבנות את ה WSDL ע"ג ה Visual Studio בעזרת יצירת פרויקט Webservice , יש ליצור פונקציות פקטיביות ולאחר מכן לראות את ה WSDL שנוצר ובכך לחסוך את כתיבת ה WSDL , המנגנון האוטמטי ב VS בהחלט עושה את העבודה.

בהצלחה.

יום שני, 5 בספטמבר 2011

Skype Api With C#


חזרתי!, אחרי חופשה ארוכה של לימודים ומחקרים עם רצף מאמרים חדשים, החלטתי להתחיל דווקא מ Skype כחלק מסדרת המאמרים הנוגעים להתממשקות ל Api שונים כמו FaceBook ו Picasa.
Skype חברת התקשורת מבוססת על תשתית האינטרנט הגדולה בעולם, היא נותנת מגון שירותים חינמים ושרותים בתשלום, וכמובן היא פופלרית מאוד בגלל הפשוטות שלה , התמיכה בריבוי פלטפורומות ובכלל שינתה את כללי המשחק בכל עולם הטלפוניה.

אז ברור שאין יותר מה להוסיף על Skype ומי שלא מכיר אותה כנראה חי במערה בשנים האחרונות כי אין ספק שזה מוצר הכרחי עבור כל אחד ואין מה לעשות אם זה חינם זה תופס מה שהפך את Skype לשחקן מוביל בעולם, אבל לא הכול חינם חלק מהשרותים בתשלום כמו שליחת Sms , להתקשר לטלפון חיצוני ושיחות ועידה לכן חברות רבות משתמשות בשירותים של Skype על מנת לבסס את מערך התקשורת בחברה ללא צורך במפעיל מקומי.

תחילה לא האמינו שהעסק יצליח ואפילו Skype עצמה לא הכחישה, ונקנתה ע"י Ebay בשנת 2005 ב מעל 2 מיליארד דולר אבל Ebay לא הצליחו למנף את המוצר למימדים שהם רצו בשנת 2011 נקנתה ע"י Microsoft בסכום עצום מעל ל 8 מיליארד דולר, ובהחלט הניפה את הדגל בעולם התקשורת והיום אחד השחקנים המובלים בו, ההשקעה של Microsoft ענקית אבל גם התמורה, בקנייה אחת Microsoft נהפכה לענקית תקשורת שסביר מאוד שתשלב את Skype במערכות הפעלה עתידיות.

ל Skype קיים Api אבל הוא מפוקפק, הוא לא ממש עובד כמו שצריך , אבל קיים הרבה מידע וקהילה מאוד פעילה שניתן להעזר בה, קיימים מספר דברים הכרחיים על מנת שנוכל לעבוד מול ה Api דבר ראשון יש להתקין את ה Skype על המכונה שעליה נכתוב את התוכנית, חשוב מאוד שהגרסה תהיה פחות מ 5.0 כי יש ב Api באג שמונע להתחבר אליו מרחוק בנוסף צריך את הקובץ Skype4COM.dll שניתן למצוא ברחבי הרשת.


 using SKYPE4COMLib;

 SkypeClass myskype = new SkypeClass();

בעזרת מחלקה זאת ניתן לבצע את כל הפעולות שקשורות שליחת SMS , התקשרות וניהול אנשי קשר, ובאופן כללי זה מאוד פשוט וניתן למצוא המון מידע כיצד לבצע את רוב הפעולות בסקייפ.

יש משהו שקצת מציק, כל פעם שנפעיל את התוכנית שלנו נבקש לאשר את התחברות ב Skype לכן קיימת אפשרות לאשר את התוכנית באופן אוטומטי.


Tools -> Options -> Advanced -> Manage other programs access skype



אתרי מידע:
http://forum.skype.com/index.php?showtopic=142821
http://www.codeproject.com/KB/cs/skypecontrolapicsharp.aspx
http://archive.msdn.microsoft.com/SEHE/Release/ProjectReleases.aspx?ReleaseId=1871

בהצלחה,

יום שבת, 5 בפברואר 2011

Json Starting Guide C#

JavaScript Object Notation - Json

היא שיטה להעברת נתונים בין מחשבים , היא נכנסה לשימוש בשנת 1999  עם כניסת סטנדרטים חדשים ב Javascript ומאפשרת שליחה של אובייקטים מסוגים שונים בצורה נוחה וברורה , היא בעצם מתחרה ב XML כי היא יותר דומה ושימושית כשפת תוכנה כחלק משפות הפיתוח הקיימות, בנוסף היא תומכת ב Xml ומאפשרת המרה בניהם, אין ספק שהשפה תפסה תאוצה בשנים האחרונות במיוחד בכל הקשור למידע משתנה, Api ו Ajax , ומאפשרת עבודה נוחה במיוחד ב Framework 3 ומעלה עם  Linq, עצם העובדה שיש לה תמיכה מרובה בשפות שכמעט זהה ל Xml מאפשרת המרה נוחה לאובייקטים בשפות שונות וחוסכת לנו תהליכי המרה מסורבלים.



המבנה של Json הוא פשוט ומורכב מ 2 אובייקטים מרכזיים : אובייקט של מידע, ומערכי מידע.

 אובייקט:
{"name":"value"}
כל אובייקט מידע מתחיל ונסגר עם סוגריים מסולסלים וגרשיים, אח"כ יש את שם האובייקט יש הפרדה בעזרת נקודתיים ואח"כ את ערך האובייקט, הערך יכול להיות בצורות של String,Boolean,Number,Null

מערך:
{"data":[{"name":"value"},{"name":"value"}]}
מערך של אובייקטים מתחיל ונסגר בסוגריים מרובעיים, הוא מכיל אובייקטים , ובין כל אובייקט חייב שהיה פסיק.

{"data": [
 {
   "id": "2132232",
   "name":
             {
               "firstname":"proxytype",
               "lastname":"blog"
              },
  "location":
              {
                "zipcode", "43823",
                 "address": "blogger.com"
               },
    "vip":"true",
    "birthday":"2010-03-24T11:16:02+0000"
  }
]}
 קיימות מחלקות רבות לעבודה עם Json ותמיכה בשפות רבות:
Java,Python,Perl,.Net
המחלקה המפורסמת ל .Net היא Json.Net וניתנת להורדה:
תחילה יש לבצע Reference עבור המחלקה ואח"כ נתחיל בבניית האובייקט שנעבוד איתו עם ה Json , ניסיתי לבנות אובייקט יחסית מורכב שיכיל בתוכו מספר אספקטים שונים בסביבת .Net הוא מכיל בתוכו הורשה מאובייקט אחר ובנוסף קיים בו מופע של אובייקט נוסף ומספר פרמטרים נוספים במטרה לסבך את העניינים.

Person
הוא יורש את אובייקט Name שמכיל בתוכו 2 מחרוזות אחת של שם פרטי ואחת של שם משפחה, בנוסף יש בו מופע של אובייקט Location שמכיל Integer של Zipcode ומחרוזות של Address, בתוך אובייקט Person יש שדות נוספים כמו Integer של ID, תאריך עבור Birthday וערך Boolean עבור Vip.

public class name
{
  [JsonProperty]
  public string Firstname;
  [JsonProperty]
  public string Lastname;
}

public class location
{
  [JsonProperty]
  public int ZipCode;
  [JsonProperty]
  public string Address;
}

public class person : name
{
  [JsonProperty]
  public location mylocation = new location();

  [JsonProperty]
  public int Id;

  [JsonProperty]
  public bool Vip;
 
  [JsonProperty]
  [JsonConverter(typeof(IsoDateTimeConverter))]
  public DateTime Birthday;

}

 [JsonProperty]
חובה להוסיף מעל כל ערך שאנו רוצים להשתמש בו עם Json.

[JsonConverter(typeof(IsoDateTimeConverter))]
המרה של תאריכים ע"י JsonConverter.

ועכשיו אחרי שיש לנו את האובייקט נבנה לנו מחלקה שקורא וממירה ל Json , תהליך העבודה עם Json מחולק ל 2 קבוצות , קבוצת כתיבה אובייקט ל Json וקבוצת המרה בין Json לאובייקט.

פונקציות ממירות:
public person json_reader()
{
   person myperson = new person();
   string json = @"{ ""mylocation"": { ""ZipCode"": 34434, ""Address"": ""blooger.com"" }, ""Id"": 0
   , ""Vip"":   true, ""Birthday"": ""2011-02-05T00:00:00+02:00"", ""Firstname"": ""proxytype"", ""Lastname"":
   ""blog"" }";
   myperson = (person)JsonConvert.DeserializeObject(json,typeof(person));
   return myperson;
}
הפונקציה קוראת את המחרוזת json וממירה אותו ל Person.

public person[] json_array_reader()
{
   person[] myperson = new person[3];
   string json = @"[ { ""mylocation"": { ""ZipCode"": 34434, ""Address"": ""blooger.com"" }, ""Id"": 0,
   ""Vip"": true, ""Birthday"": ""2011-02-05T00:00:00+02:00"", ""Firstname"": ""proxytype"", ""Lastname"":
   ""blog"" }, { ""mylocation"": { ""ZipCode"": 34434, ""Address"": ""blooger.com"" }, ""Id"": 1, ""Vip"": true,
   ""Birthday"": ""2011-02-05T00:00:00+02:00"", ""Firstname"": ""proxytype"", ""Lastname"": ""blog"" },  
   { ""mylocation"": { ""ZipCode"": 34434, ""Address"": ""blooger.com"" }, ""Id"": 2, ""Vip"": true, 
   ""Birthday"": ""2011-02-05T00:00:00+02:00"", ""Firstname"": ""proxytype"", ""Lastname"": ""blog"" } ] ";
  
   myperson = (person[])JsonConvert.DeserializeObject(json, typeof(person[]));
   return myperson;
}
הפונקציה קוראת את המחרוזת json ומחזירה מערך של 3 Person.
 
פונקציות כתיבה:
public string json_Writer()

{
   myperson = new person();
   myperson.Firstname = "proxytype";
   myperson.Lastname = "blog";
   myperson.mylocation.Address = "blooger.com";
   myperson.mylocation.ZipCode = 34434;
   myperson.Vip = true;
   myperson.Birthday = DateTime.Now.Date;
   string json = JsonConvert.SerializeObject(myperson, Formatting.Indented);
   return json;
}
הפונקציה ממירה את האובייקט Person למחרוזת Json.

public string json_array_writer()
{
   person[] myarray = new person[3];
   for (int i = 0; i < myarray.Length; i++)
   {
      myarray[i] = new person();
      myarray[i].Firstname = "proxytype";
      myarray[i].Lastname = "blog";
      myarray[i].Id = i;
      myarray[i].mylocation.Address = "blooger.com";
      myarray[i].mylocation.ZipCode = 34434;
      myarray[i].Vip = true;
      myarray[i].Birthday = DateTime.Now.Date;
    }

    string json = JsonConvert.SerializeObject(myarray, Formatting.Indented);
    return json;
}

הפונקציה ממירה מערך של Person למחרוזת Json.
לסיכום:
Json נוחה יותר מ Xml ומאפשרת המרה מהירה וחסכונית בין Json לאובייקטים בקוד , היא חוסכת המון שורות קוד של המרות ובעצם מקצרת את תהליך הכתיבה וההמרה.

יום שבת, 15 בינואר 2011

Picasa Api With C#



לאחר המאמר שלי בנושא התממשקות ל Facebook החלטתי לעשות מאמר נוסף על התממשקות ל Picasa - תוכנת האחסון תמונות ב Google, אז גם פה הנושא הוא מורכב ואפילו יותר מורכב מ Facebook (אם חשבתם ש Facebook מסובך תראו מה Google עשו לנו).

קצת רקע:
הרעיון של ה Api  הוא לאפשר לאפליקציות צד שלישי לעבוד מול התכנים והחשבונות של המשתמשים ובעצם לקבל תשתית מלאה לביצוע שאילתות על התוכנות של Google.

גוגל מאוד רחבה מבחינת התשתיות שהיא נותנת עבור חברות צד שלישי כמעט כל המוצרים של גוגל מכילים רכיבי Api עבור התממשקות חיצונית ואם סתם בא לי לבנות עכשיו מערכת לניהול תמונות אני יכול לעשות זאת בעזרת ה Api של Picasa בנקודת הנחה שהיא מיועדת למשתמשים עם חשבון ב Picasa וכך אני יכול לעשות לשאר האפליקציות של Google כמו Google Maps , Google Earth , Gmail ועוד.

יופי שזה אפשרי אבל מה בנוגע לפרטיות של החשבונות שלי?

מרבית ה Apis בדומה ל Faceook / Google מכילים מספר כלי אימות והצפנה על מנת לשמור על מידע של המשתמשים, גוגל מאפשרת זאת במספר דרכים שעליהם אני אפרט בהמשך, כרגיל גם המאמר הזה מחולק לחלקים, יצירת חשבון ב Google והוספת Domain ב Webmaster tool, תהליך ה Authentication, ביצוע שאילתה וקבלת נתונים.

הגדרות ב Google
תחילה יש ליצור חשבון ב Google (אני לא מאמין שלמשהו אין אבל בכל מקרה זה חובה), לאחר מכן יש להצהיר על הדומיין שלנו בגוגל דרך הלינק https://www.google.com/accounts/ManageDomains , יש לרשום את הדומיין שלנו על מנת ש Google היפתח לנו את הגישה ל Api




ניתן לבחור דרכים שונות לאימות אני בחרתי Add a meta tag to your site's home page , זאת שורת Metadata שנשתול בעמוד הראשי של ה Domain שלנו.


 
לאחר שהוא יגש אליו ויאמת אותו הוא יכריז שהוא Active וייצר לנו מספר מפתחות בדומה ל Facebook


  • Target Url Path Prefix - הכתובת המלאה של הדף שהולך להתחבר ל Picasa ב domain שלנו לדוגמה: http//www.mysite.com/picasa.aspx
  •  Domain Description - ניתן לתת תיאור אבל הוא לא חובה.
  • Upload New X509 - ניתן לתת Certificate שעליו נדבר בהמשך אבל גם הוא לא חובה.


כלים נחוצים:

Google Data Protocol - המחלקות שאיתם נתממשק דרך הקוד שלנו באתר, התמיכה מרובה וניתן למצוא מחלקות להמון שפות כמו Java , Javascript , PHP,Python,.Net , להורדה: Client Libraries

OpenSSL - כלי ליצירת Certificates חינמי, להורדה: OpenSSL - Windows

סקירה על המחלקות שבהם נשתמש:
  • Google.GData.Client.dll
  • Google.GData.Extensions.dll
  •  Google.GData.Photos.dll

מחלקות ה Client  וה Extensions קבועות עבור כל סוגי ה Apis ש Google מאפשרת לנו להתממשק אליהם עבור כל Api יש קובץ התממשקות משלו, במקרה של אנחנו משתמשים ב Photos אם ההיתי מעוניין להשתמש בשירות אחר עליי לצרף את המחלקה שמייצגת אותו לפרוייקט.

Authentication

תהליך האימות של האפליקציה שלנו גמיש , עבור תוכנות מבוססות Web ותוכנות מבוססות Desktop גם רמת האבטחה ניתנת לשינוי בחלק זה נעבור כיצד ניתן לאמת את החשבונות של המשתמשים.

קיימים 2 ערוצי התממשקות:

1.Client Authentication

הכנסת שם משתמש וסיסמא לחשבון של Google , הדרך הזאת נפוצה באפליקציות Desktop שמעוניינות להתממשק ל Picasa אבל מאוד לא מומלצת לאתרים שמעונינים להתממשק ל Picasa כי המשתמש צריך להכניס את פרטי ההתחברות שלו בתוך האתר שלנו, סביר להניח שהוא לא יעשה את זה מטעמי אבטחת מידע.


2. Web Application Client Authentication

הדרך הטובה ביותר להתממשקות של אתרים צד שלישי למערכות ה Api ללא צורך להתממשקות דרך האתר אלא בעזרת Token של ה Session של המשתמש, כלומר המשתמש צריך להיות מחובר לחשבון שלו ב Google , והמערכת שלנו לוקחת את ה Session שלו מ Google.

אם אנחנו לא נשתמש ב Certificate נראה את ההודעה הבאה:
נראה סימן קריאה צהוב שאומר רק אם המשתמש סומך על האתר שיאשר את הכניסה כלומר Google לא מכיר את ה Domain שלנו כאתר אמין, אלא אם כן נצור Certificate ונעלה אותו ל Google ב Manage Domain שהראיתי מקודם אבל אל דאגה נעבור גם על זה.
עכשיו נעבור על הקוד שלנו על מנת להבין את התממשקות, תחילה ניצור לנו אתר אינטרנט חדש ב Visual Studio, ונצרף אליו את המחלקות מה Sdk של Google , נלך לפונקציה Page_Load.

הבדיקה הראשונה שלנו בודקת אם אין לנו Token שגוגל הפיק לנו עבור המשתמש, אם אין Token נעשה את הקוד הבא:


 if (Request["token"] == null)
{
  Session["tokan"] = null;
  string d = AuthSubUtil.getRequestUrl("http://mywebsite.com/picasa.aspx", 
  "http://picasaweb.google.com/data/", false, true);
   Response.Redirect(d);
}
עכשיו נעבור לנו על הקוד, יש לנו אובייקט שנקרא AuthSubUtil שהוא הכלי שמנהל לנו את התממשקות , GetRequest זאת הפונקציה ששולחת את המשתמש מהאתר שלנו לאתר של Google על מנת שיאשר את התתחברות ל Domain שלנו, הפונקציה מקבלת קבוצה של פרמטרים שעליהם אני אפרט:

1.Url - הכתובת הראשונה שאנו רואים http://mywebsite.com/picasa.aspx זאת הכתובת שהמשתמש יחזור אליה מ Google לאחר שיאשר את ההתממשקות.

2.Url Api - זאת הכתובת שמייצגת את הכתובת של ה Api של Google לשם המשתמש יעבור לאחר שהפונקציה הזאת תופעל - לכל מוצר יש את כתובת ה Api שלו.

3.Bool Secure - מייצג אם יש Certificate עבור ה Domain שלנו.

4.Bool Session - אם לקבל מפתח חד פעמי שניתן לבצע איתו פעולה בודדת או לקבל מפתח של ה Session עצמו שניתן לבצע בעזרתו פעולות רבות.

לאחר מכן נבצע Redirect עלמנת לתפוס את ה Token שחזר לנו.


 Google Certificate

יצירת Certificate מתבצעת בעזרת הכלי OpenSSL (להורדה גש לשלב "כלים נחוצים"), פורמט התעודה שלנו הוא X.509 , נצטרך לעשות Private Key ואת ה Certificate Key של התעודה, נעשה זאת בעזרת הפקודה הבאה:

C:\OpenSSL-Win32\bin>openssl req -x509 -nodes -days 365 -newkey rsa:1024 -sha1 -subj
"/C=US/ST=CA/L=Mountain View/CN=www.mysite.com" -keyout
test_key.pem -out test_cert.pem 

השורה האדומה מסמנת לנו את פרטי החברה שעליה רשום ה Certificate שלנו:
C-Country
ST- State
L-Location
CN - Company name

לאחר פקודה זו נוצרו לנו 2 קבצי Pem שאת קובץ test_cert.pem נעלה ל Google, ב Manage Domains שראינו בהתחלה.

השלב הבא הוא יצירת קובץ Pfx שנוכל לעבוד בו עם האפליקציה שלנו ב .Net שמכיל את המפתח הפרטי שלנו, נריץ את הפקודה הבאה:

C:\OpenSSL-Win32\bin>openssl pkcs12 -export -in test_cert.pem -inkey test_key.pem
-out test_cert.pfx -name "MyCertificate"

עכשיו נחזור לקוד של ההתממשקות:

string d = AuthSubUtil.getRequestUrl("http://mywebsite.com/picasa.aspx", "http://picasaweb.google.com/data/", true, true);

ונסמן את ה bool Secure כ True, נעלה את קובץ ה Pfx לאתר שלנו.

נוסיף לנו פונקציה נוספת בקוד שלנו שבה נשתמש בהמשך:

private AsymmetricAlgorithm getRsaKey()
{
  X509Certificate2 cert = new X509Certificate2(Server.MapPath("~/test_cert.pfx"),"certificatepassword");
  RSACryptoServiceProvider privateKey = cert.PrivateKey as RSACryptoServiceProvider;
  return privateKey;
}

הפונקציה תקרא מקובץ ה Pfx את המפתח הפרטי שלנו ו Google תאמת אותו מול קובץ ה Pem שהעלנו עבור ה Domain ב Google.

עכשיו נחזור לנו להמשך התהליך, נניח שקיבלנו את ה Token שלנו מ Google עכשיו נעשה בדיקה אם יש לנו Token נריץ את הקוד הבא:

 if (Request["token"] != null)

{
  string token = Request.QueryString["token"];
  Session["token"] = AuthSubUtil.exchangeForSessionToken(token, null).ToString();
  Response.Redirect(Request.Url.AbsolutePath, true);
}

 מה שאנחנו בעצם עושים הוא לקחת את ה Token מה Request ונבקש מ Google בעזרת הכלי AuthSubUtil שיחזיר לנו Token של ה Session , הפונקציה exchangeForSessionToken מקבלת 2 ערכים הראשון הוא ה Tokan ש Google החזיר לנו בשלב ההתממשקות הראשונית, הפרמטר השני זה ההצפנה , אם אין לנו Cetificate Private Key נשלח Null , אם יש Cetificate Private Key נקרא לפונקציה שקוראת את המפתח מקובץ ה Pfx שיצרנו.

Session["token"] = AuthSubUtil.exchangeForSessionToken(token, getRsaKey()).ToString();


ב 2 המצבים צריכים לטעון את ה Token שחוזר ב Session של האתר שלנו על מנת שנוכל לבצע יותר מפעולה בודדת, ובעצם סיימנו את תהליך ההתממשקות ועכשיו נעבור לשאילתות מול ה Api.

ביצוע שאילתות מול ה Api

לאחר שסיימנו את תהליך ההתממשקות ניתן להתחיל לבצע שאילתות מול ה Api של Google, תחילה נצהיר על האובייקט:
GAuthSubRequestFactory - שהוא מכיל בתוכו את ה Tokan שבתוך ה Session של האתר שלנו , ובעצם נשלח ל Google ברגע שנבצע שאילתה, בנוסף צריך להגדיר את ה Api של התוכנה Picasa שהקוד שלה הוא "lh2" ,שוב פעם לכל Api יש את הקוד שלו (לרישמת הקודים עבור שאר האפליקציות), וכמובן נשלח לו את ה Domain שלנו כ ApplicationName.

GAuthSubRequestFactory authFactory = new GAuthSubRequestFactory("lh2", "http://www.mywebsite.com/");
authFactory.Token = Session["token"].ToString();
 
השלב הבא הוא להצהיר על ה Service עצמו, האובייקט שלנו הוא PicasaService שמקבל ApplicationName שהגדרנו באובייקט GAuthSubRequestFactory.
 
PicasaService myservice = new PicasaService(authFactory.ApplicationName);

נצהיר על סוג השאילתה שלנו (Query) , יש המון סוגים של שאילתות, בדוגמה שנראה פה נשתמש ב PhotoQuery שהיא שאילתה עבור התמונות ללא קשר לאלבום אבל ניתן לבצע שאילתה גם על אלבומים בעזרת האובייקט AlbumQuery.

 PhotoQuery query = new PhotoQuery(PicasaQuery.CreatePicasaUri("default"));

ה default מייצג את ה User במקרה של Client Authentication נשלח שם משתמש וסיסמא:
PhotoQuery query = new PhotoQuery(PicasaQuery.CreatePicasaUri(username,password));


אובייקט PicasaQuery בונה לנו את ה Url שאליו אנו פונים ב Api.

את התוצאות שחוזרות לנו בפורמט Xml נאחסן באבייקט PicasaFeed.
PicasaFeed feed = myservice(query)

מה שנשאר לנו לעשות הוא להריץ ריצה על ה Feed על מנת לחלץ משם את התמונות שחזרו לנו מה Api.
foreach (AtomEntry aentry in feed.Entries)
{
myphotos = myphotos +  aentry.Content.Src.ToString();
}
 
קוד מלא לדוגמה:
 
using Google.GData.Photos;
using Google.GData.Client;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography;
using System.Net;

public partial class picasa : System.Web.UI.Page
{
   public string myphotos = "";
   public string myerror = "";
   protected void Page_Load(object sender, EventArgs e)
   {
      if (Session["token"] != null)
     {
       get_images();
     }
     else if (Request["token"] != null)
     {
       string token = Request.QueryString["token"];
       Session["token"] = AuthSubUtil.exchangeForSessionToken(token, null).ToString();
       Response.Redirect(Request.Url.AbsolutePath, true);
     }
     else if (Request["token"] == null)
      {
       Session["tokan"] = null;
       string d = AuthSubUtil.getRequestUrl("http://www.mywebsite.com/picasa.aspx", 
       "https://picasaweb.google.com/data/", false, true);
       Response.Redirect(d);
      }
}

private void get_images()
{
  GAuthSubRequestFactory authFactory = new GAuthSubRequestFactory("lh2", "http://www.mywebsite.com/");
  authFactory.Token = Session["token"].ToString();
  PicasaService myservice = new PicasaService(authFactory.ApplicationName);
   picasaser.RequestFactory = authFactory ;
   try
   {
     PhotoQuery query = new PhotoQuery(PicasaQuery.CreatePicasaUri("default"));
     PicasaFeed feed = myservice.Query(query);
     foreach (AtomEntry aentry in feed.Entries)
    {
      myphotos = myphotos + aentry.Content.Src.ToString() ;
    }
   }
   catch (GDataRequestException gdre)
   {
     HttpWebResponse response = (HttpWebResponse)gdre.Response;
     //bad auth token, clear session and refresh the page
      if (response.StatusCode == HttpStatusCode.Unauthorized)
     {
      Session["tokan"] = null;
      Response.Redirect(Request.Url.AbsolutePath, true);
     }
     else
     {
       Response.Write("Error processing request: " + gdre.ToString());
     }
   }
}

private AsymmetricAlgorithm getRsaKey()
{
  X509Certificate2 cert = new X509Certificate2(Server.MapPath("~/test_cert.pfx"),"mycertificatepassword");
  RSACryptoServiceProvider privateKey = cert.PrivateKey as RSACryptoServiceProvider;
  return privateKey;
 }
}

לאתרי מידע נוספים:

בהצלחה...

יום שלישי, 11 בינואר 2011

#Facebook api with C



התממשקות ל Facebook זה לא דבר פשוט עם #C ולמעשה דורשת מספר הכנות ושינויים בשביל להשלים את התהליך, המאמר מחולק ל 3 חלקים, החלק הראשון נוגע בהגדרות החשבון שלנו ב Facebook החלק השני נוגע בחלקים הדרושים על מנת לבצע את הגדרות ההתממשקות שלנו כמו שצריך, והחלק האחרון נוגע באפליקציה שלנו.

הגדרות ב Facebook
הכרה של Facebook במערכת שלנו, על מנת לעשות זאת יש ליצור אפליקציה בתוך Facebook עצמו, תחילה יש ליצור חשבון ב Facebook, השלב הבא הוא להיכנס לקישור Developers  (מרכז האפליקציות בחשבון שלנו ב Facebook),לבחור ב See My Apps או ליצור אפליקציה חדשה בלחיצה על Create  one.

בשלב זה תכניסו תיאור ושם לאפליקציה ותשמרו, Facebook מייצר מספר מפתחות עבור האפליקציה שלנו.

appId
מספר חד ערכי עבור האפליקציה שלנו.

apiKey
מפתח עבור ה Api.

appSecret
מפתח עבור האפליקציה.

שים לב! שמור את המפתחות האלה במקום בטוח!



חשוב מאוד להגדיר את כתובת האתר שהולך לעבוד מול האפליקציה הזאת על מנת לאשר את החיבור שלו ל Api של Facebook , חשוב לציין נקודה שעדיין מוקדמת בתהליך אבל קריטית - עם ננסה להתממשק דרך אתר מקומי - (LocalHost) שאותו נפתח בשלבים הבאים, לא נוכל לעשות זאת , האתר חייב להיות עם כתובת חוקית.

התקנת רכיבים לצורך התממשקות:
על מנת לאפשר התממשקות אנחנו צריכים להוריד את ספריות ה Api של Facebook לאתר שלנו ולעשות שינויים ב web.config וב Framework שלנו.

Framework
יש להוריד ולהתקין את Framework 3.5.

Facebook Api
מחלקות ה Api של Facebook להורדה FacebookSDK.

ה Api מורכב ממספר מחלקות שמחוייבות להיות קשורות לאפליקציה שלנו על מנת לעבוד:

Facebook.dll
מחלקות כלליות של ה Api.

 Facebook.Web.dll
מחלקות ה Web של ה Api.

Microsoft.Contracts.dll
מערכת חדשה של מיקרוסופט לטיפול בשגיאות ובקלט \ פלט.
להורדה Microsoft contracts

 Newtonsoft.Json.dll
מחלקה לעבודה עם Json ו .Net.
להורדה Json.net

הקמת פרויקט התממשקות
הדבר הראשון שנעשה הוא פרויקט חדש ב Visual Studio של Asp.net ב Framework 3.5, אח"כ נעשה Reference למחלקות שהורדנו



יש לערוך את קובץ ה web.config על מנת שיוכל להכיר את כל ה components.
לפני התגית  </configsections> יש להכניס:
<section name="facebookSettings" type="Facebook.FacebookConfigurationSection" />

אחרי התגית <\connectionstrings>יש להכניס:
<facebooksettings appid="xxxxxxxxxxxx" appsecret="xxxxxxxxxxxx"
cookiesupport="true" / >
בנקודה זו יש להכניס את המפתחות ש Facebook יצר לנו עבור ההתממשקות ל Api.

נערוך את דף ה Index של האתר שלנו:
נוסיף לתגית < html> בראש העמוד:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:fb="http://www.facebook.com/2008/fbml">


נכניס לתוך ה < body>  את הטופס הבא:

<form id="form1" runat="server">
    <div>
              <div id="fb-root">
     </div>
     <fb:login-button autologoutlink="true" onlogin="window.location.reload();"
        perms="email"></login-button>
     <script type="text/javascript">
        window.fbAsyncInit = function () {
         FB.init({ appId: 'xxxxxxxxxxxx', status: true, cookie: true, xfbml: true, 
         reloadIfSessionStateChanged:  true });
         };
         (function () {
         var e = document.createElement('script');
         e.type = 'text/javascript'
         e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';
         e.async = true;
         document.getElementById('fb-root').appendChild(e);
         } ());
</script>
User ID:<label id="LabelUserid" runat="server"></label>
First Name:<label id="LabelFirstName" runat="server">lt;/label>
Last Name:<label id="LabelLastName" runat="server">lt;/label>
<img id="imageUser" runat="server" visible="true" /></img</div>
</form>

עכשיו נערוך את הקוד שמאחרי הדף:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Facebook;
using Facebook.Web;
using System.IO;

public partial class facebook : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
   {
       FacebookApp fapp = new FacebookApp();
       Authorizer auth = new Authorizer(fapp);
       auth.Perms = "email";

       if (auth.IsAuthorized())
      {
        LabelUserid.Text = fapp.UserId + "";
        JsonObject result = (JsonObject)fapp.Api("/me");
        LabelFirstName.Text = (String)result["first_name"];
        LabelLastName.Text = (String)result["last_name"];
        imageUser.ImageUrl = "http://graph.facebook.com/" + fapp.UserId + "/picture
        ?type=large";
        imageUser.Visible = true;
      }
   }
}

קיבלנו אובייקט Json מה Api ועכשיו אנו שולפים את הפרמטרים של ה Profile של המשתמש באפליקציה בעצם ביצענו Login in ל Facebook, ה Api עם המון אפשרויות וניתן לעשות דברים נוספים כמו הוספת תגובות, קריאה והעלת תמונות ועוד ,החלק העיקרי הוא שלב ההתממשקות ובעצם כל אפליקציה שניצור ב Facebook מחייבת התחברות של המשתמש לחשבון האישי שלו כמובן שזה מצריך אישור של המשתמש.

הדף של האפליקציה שלנו:
הדף לאחר ההתממשקות:

נשמור את הפרויקט ונעלה אותו לשרת.
בהצלחה...