موبایل (اندروید در اندروید استودیو)

برنامه نویسی موبایل با اندروید استودیو

درس بعدی ||||| درس قبلی

برای این مطلب نیاز است ابتدا مطالب مربوط به لینک های زیر را مطالعه کنید:

ثبت کاربر در MySQL بصورت شی گرا

اتصال به بانک اطلاعاتی و درج رکورد جدید

پس از مطالعه مطالب فوق باید در اندروید استودیو کتابخانه Volley را به برنامه اضافه کنیم. بنابراین نیاز است به نحوه کار با کتابخانه Volley هم آشنا باشیم. لینک زیر را برای مطالعه می توانید استفاده کنید:

آموزش کار با کتابخانه Volley به همراه مثال کاربردی

یک کلاس جدید به نام Constants می سازیم و آدرس فایل php ساخته شده را در آن قرار می دهیم. کد آن بصورت زیر است:

public class Constants
{
    public static final String Root_URL="http://10.0.0.34:81/PHPpost/v1/registerUser.php";
}

در مرحله بعدی سطح دسترسی (permission) در فایل مانیفست (Manifest.xml) را نباید فراموش کنیم:

<uses-permission android:name="android.permission.INTERNET"/>

حال نوبت به طراحی فایل activity_main.xml میرسد. کد آن در زیر آمده است:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/linearLayout"
        android:orientation="vertical"
        android:layout_centerVertical="true">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="userName"/>
        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Enter user name"
            android:inputType="textPersonName"
            android:id="@+id/edt_username"
            />
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Password"/>
        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Enter user name"
            android:inputType="textPassword"
            android:id="@+id/edt_password"
            />
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="email"/>
        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Enter user name"
            android:inputType="textEmailAddress"
            android:id="@+id/edt_email"
            />
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Save"
            android:id="@+id/btn"
            android:layout_gravity="center"/>
    </LinearLayout>

</RelativeLayout>

حال باید در عمومی سه editText و یک دکمه (Button) تعریف شوند:

 EditText edtUsername,edtPassword,edtEmail;
    Button btn;

در متد onCreate کد زیر نوشته می شود:

 edtUsername=findViewById(R.id.edt_username);
        edtPassword=findViewById(R.id.edt_password);
        edtEmail=findViewById(R.id.edt_email);
        btn=findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                registerUser();
            }
        });

متد registerUser در ادامه و خارج از onCreate و داخل کلاس MainActivity ساخته می شود:

 private void registerUser() {
        final String email=edtEmail.getText().toString().trim();
        final String username=edtUsername.getText().toString().trim();
        final String password=edtPassword.getText().toString().trim();
        //Toast.makeText(this, "aaa", Toast.LENGTH_SHORT).show();
        StringRequest stringRequest=new StringRequest(Request.Method.POST, Constants.Root_URL, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                try {
                    JSONObject jsonObject=new JSONObject(response);
                    Toast.makeText(MainActivity.this, jsonObject.getString("message")+"aaa", Toast.LENGTH_SHORT).show();
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
               // Toast.makeText(MainActivity.this, "error:"+error.getMessage(), Toast.LENGTH_SHORT).show();
                Log.e("TAG","error: "+error.getMessage());

            }
        }){
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {

                Map<String,String> params=new HashMap<>();
                params.put("username",username);
                params.put("email",email);
                params.put("password",password);
                return params;
            }
        };
        RequestQueue requestQueue= Volley.newRequestQueue(this);
        requestQueue.add(stringRequest);


    }

همانطوریکه مشاهده می شود کد فوق دارای چند مرحله است: در مرحله اول مقادیر وارد شده در کادرهای متنی در متغیرهای رشته ای قرار می گیرند:

final String email=edtEmail.getText().toString().trim();
final String username=edtUsername.getText().toString().trim();
final String password=edtPassword.getText().toString().trim();

به کمک کتابخانه Volley درخواست با کلاس StringRequest داده می شود که شامل دو رویداد دریافت پاسخ onResponse و دریافت خطا onErrorمی باشد:

 StringRequest stringRequest=new StringRequest(Request.Method.POST, Constants.Root_URL, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                try {
                    JSONObject jsonObject=new JSONObject(response);
                    Toast.makeText(MainActivity.this, jsonObject.getString("message")+"aaa", Toast.LENGTH_SHORT).show();
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
               // Toast.makeText(MainActivity.this, "error:"+error.getMessage(), Toast.LENGTH_SHORT).show();
                Log.e("TAG","error: "+error.getMessage());

            }
        })

در onResponse به کمک شی از کلاس JSONObject پاسخ درخواست به سرور دریافت می شود و به کمک متد ErrorListener زمانی اجرا می شود که در دریافت پاسخ خطایی رخ دهد.

جهت ارسال پارامترها به سرور نیازداریم که از متد getParams استفاده کنیم. کد آن بصورت زیر آمده است:

protected Map<String, String> getParams() throws AuthFailureError {

    Map<String,String> params=new HashMap<>();
    params.put("username",username);
    params.put("email",email);
    params.put("password",password);
    return params;
}

در انتها نیز باید درخواست تکمیل شده و به صف درخواست ها اضافه شود:

 RequestQueue requestQueue= Volley.newRequestQueue(this);
 requestQueue.add(stringRequest);

برنامه را اجرا بگیرید. باید بتوانید رکورد جدیدی ثبت کنید.

درس قبلی ||||| درس بعدی

قبل از شروع مطالعه باید با آموزش زیر آشنا باشید:

تحلیل فایل json در اندروید استودیو

جهت ارتباط با اینترنت باید کتابخانه Volley را به اندروید استودیو اضافه کرد. برای این منظور در فایلbuild.gradle کد زیر را به قسمت dependencies اضافه کنید.

implementation 'com.android.volley:volley:1.1.1'

پس از افزودن کد فوق باید مجوز استفاده از اینترنت را دریافت کرد بنابراین ابتدا در manifest کد زیر را اضافه می کنیم:

<uses-permission android:name="android.permission.INTERNET"/>

سپس باید مجوز را برای نسخه های اندروید بالای۲۴ نیز بدست آورد که این کار در کلاس MainAcitivty انجام می شود:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.INTERNET)!= PackageManager.PERMISSION_GRANTED){
        Toast.makeText(this, "مجوز نیاز است", Toast.LENGTH_SHORT).show();
    }else {
        Toast.makeText(this, "مجوز قبلا دریافت شده است", Toast.LENGTH_SHORT).show();
        requsetData();
    }
}

چنانچه مجوز دریافت شده باشد متد requestData فراخوانی می شود. قبل از فراخوانی این متد باید ابتدا آدرس سایتی که API برای هواشناسی را پشتیبانی می کند در نظر بگیریم. سایت https://api.openweathermap.org برای این منظور مناسب است. نکته ای که وجود دارد باید در این سایت ثبت نام کرد و یک APIKEY‌ دریافت نمود که رایگان است و براحتی می توانید با جستجو در سایت این کار را انجام دهید. سپس برای اطمینان از درستی آدرس، آنرا در نرم افزار postman آزمایش کنید. عکس زیر آزمایش آدرس برای دریافت کد JSON می باشد:

اطلاعات بدست آمده از آدرس فوق که برای شهر Sari می باشد به صورت زیر است:

{
    "coord": {
        "lon": 53.06,
        "lat": 36.56
    },
    "weather": [
        {
            "id": 803,
            "main": "Clouds",
            "description": "broken clouds",
            "icon": "04n"
        }
    ],
    "base": "stations",
    "main": {
        "temp": 12,
        "feels_like": 10.55,
        "temp_min": 12,
        "temp_max": 12,
        "pressure": 1025,
        "humidity": 87
    },
    "visibility": 7000,
    "wind": {
        "speed": 2.1,
        "deg": 60
    },
    "clouds": {
        "all": 75
    },
    "dt": 1606923772,
    "sys": {
        "type": 1,
        "id": 7498,
        "country": "IR",
        "sunrise": 1606879351,
        "sunset": 1606914743
    },
    "timezone": 12600,
    "id": 116996,
    "name": "Sari",
    "cod": 200
}

اطلاعاتی که مورد نیاز است شامل نام شهر name، نام کشور که در json object با نام sys قرار دارد و نام آن country است. همچنین دما که در json object با نام name قرار دارد که رشته آن temp است. برای آب و هوا نیز در json Array با نام wheather است که در اندیس ۰ آرایه قرار دارد و رشته آن main , description است. با کمی دقت در کد JSON فوق متوجه خواهید شد.

حال رشته URLرا به صورت زیر به صورت عمومی به اندروید استودیو اضافه می کنیم:

public static final String URL_FORMAT="https://api.openweathermap.org/data/2.5/weather?q=%s&units=metric&appid=44e44e807c21dbce14c4cbcc02723dcc";

مقدار s% که در رشته فوق مشاهده می شود دریافت نام شهر از ورودی است. اکنون وقت آن است که طراحی اکتیویتی را انجام دهیم:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/city"
        android:text="Tehran"
        android:layout_marginTop="70dp"
        android:textSize="26sp"
        android:layout_marginLeft="40dp"
        />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/temp"
        android:layout_centerInParent="true"
        android:text="40"
        android:textSize="76sp"
        android:textColor="@color/colorPrimary"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/weather"
        android:layout_below="@id/temp"
        android:text="Rain"
        android:layout_centerHorizontal="true"
        android:textColor="@android:color/holo_purple"
        android:textSize="26sp"/>

اکنون باید عناصر اکتیویتی را به کلاس MainActivity بشناسانیم: در عمومی کد زیر را می نویسیم:

TextView tvCity,tvTemp,tvWeather;

در متد onCreate کد زیر را می نویسیم:

 tvCity=findViewById(R.id.city);
        tvTemp=findViewById(R.id.temp);
        tvWeather=findViewById(R.id.weather);

حال برای دریافت اطلاعات و نمایش در اکتیویتی متد RequestData به صورت زیر تعریف می شود:

همانطوریکه مشاهده می شود ابتدا نام شهر دریافت می شود و در رشته قرار می گیرد:

 String url=String.format(Locale.getDefault(),URL_FORMAT,"Sari");

سپس اشیای Volley فراخوانی می شوند: ابتدا شی از کلاس JSONObjectRequset فراخوانی می شودکه دارای آرگومانهای روش دریافت اطلاعات، آدرس است. کد JSON دریافتی در response قرار می گیرد:

 JsonObjectRequest request=new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                Log.i("TAG","response: "+response.toString());
                //Toast.makeText(MainActivity.this, response.toString(), Toast.LENGTH_SHORT).show();
                try {
                    tvWeather.setText(response.getJSONArray("weather").getJSONObject(0).getString("main"));
                    tvWeather.append(": "+response.getJSONArray("weather").getJSONObject(0).getString("description"));

                    tvCity.setText(response.getString("name").toUpperCase()+", "+ response.getJSONObject("sys").getString("country"));

                    double temp=response.getJSONObject("main").getDouble("temp");
                    tvTemp.setText(temp+"");
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e("TAG", "onErrorResponse: Error");
            }
        });

برای دریافت اطلاعات نیز باید از کلاس RequestQueue استفاده کرد. و متد add این کلاس درخواست را دریافت کرده و در response می چیند:

RequestQueue queue= Volley.newRequestQueue(this);
 queue.add(request);

حال برنامه را اجرا می کنیم. چنانچه مجوز اینترنت دریافت شده بود و خطایی مشاهده نکردید باید اکتیویتی به شکل زیر را ببینید:

درس بعدی |||||‌ درس قبلی

JSON مخفف JavaScript Object Notation است. این یک قالب تبادل داده مستقل است و بهترین جایگزین برای XML است. در این درس نحوه تجزیه پرونده JSON و استخراج اطلاعات لازم از آن توضیح داده شده است.

اندروید چهار کلاس مختلف برای دستکاری داده های JSON فراهم می کند. این کلاسها JSONArray ، JSONObject ، JSONStringer و JSONTokenizer هستند.

اولین قدم ، شناسایی فیلدهای موجود در داده های JSON است که به آنها علاقه دارید. به عنوان مثال. در JSON که در زیر آورده شده است ما علاقه مندیم فقط دما را بدست آوریم.

{
   "sys":
   {
      "country":"GB",
      "sunrise":1381107633,
      "sunset":1381149604
   },
   "weather":[
      {
         "id":711,
         "main":"Smoke",
         "description":"smoke",
         "icon":"50n"
      }
   ],
	
  "main":
   {
      "temp":304.15,
      "pressure":1009,
   }
}

JSON – عناصر
یک پرونده JSON از اجزای بسیاری تشکیل شده است. در اینجا جدول تعریف اجزای یک فایل JSON و شرح آنها است –

1 Array ([): در یک پرونده JSON ، براکت مربع ([) یک آرایه JSON را نشان می دهد

2 شی ({): در یک فایل JSON ، آکولاد ({) نمایانگر یک شی JSON است

3 کلید: یک شی JSON شامل یک کلید است که فقط یک رشته است. جفت کلید / مقدار یک شی J JSON را تشکیل می دهد

4 Value: هر کلید دارای مقداری است که می تواند رشته ای ، صحیح یا غیره باشد.

تجزیه و تحلیل JSON
برای تجزیه و تحلیل یک شی JSON ، ما یک شی از کلاس JSONObject ایجاد می کنیم و یک رشته حاوی داده های JSON را برای آن مشخص می کنیم. نحو آن بصورت زیر است:

String in;
JSONObject reader = new JSONObject(in);

آخرین مرحله تجزیه JSON است. یک پرونده JSON از اشیای مختلفی با جفت کلید / مقدار متفاوت تشکیل شده است. بنابراین JSONObject عملکرد جداگانه ای برای تجزیه هر یک از مولفه های پرونده JSON دارد. نحو آن در زیر آورده شده است :

JSONObject sys  = reader.getJSONObject("sys");
country = sys.getString("country");
			
JSONObject main  = reader.getJSONObject("main");
temperature = main.getString("temp");

متد getJSONObject شی JSON را برمی گرداند. متد getString مقدار رشته کلید مشخص شده را برمی گرداند. جدا از این روشها ، روشهای دیگری نیز برای تجزیه بهتر فایلهای JSON توسط این کلاس ارائه شده است. این روش ها در زیر ذکر شده است:

1 get (نام رشته): این روش فقط مقدار را برمی گرداند اما به شکل نوع Object است

2 getBoolean (نام رشته) این روش مقدار بولی مشخص شده توسط کلید را برمی گرداند

3 getDouble (نام رشته) این روش مقدار دوگانه مشخص شده توسط کلید را برمی گرداند

4 getInt (نام رشته) این روش مقدار صحیح مشخص شده توسط کلید را برمی گرداند

5 getLong (نام رشته) این روش مقدار طولانی مشخص شده توسط کلید را برمی گرداند

6 length () این روش تعداد نگاشت های نام / مقدار را در این شی برمی گرداند.

7 names () این روش آرایه ای را شامل می کند که شامل نام رشته ها در این شی باشد.

مثال: برنامه ای بنویسید که فایل JSON که حاوی اطلاعات دانشجو است را مورد تجزیه و تحلیل قرار دهد و در یک لیست ویو نمایش دهد.

این فایل با پسوند json است که محتوای آن بصورت زیر است:

 [
      {
         "name": "ali",
         "lastname": "alavi",
         "phone": "1912"
      },
      {
         "name": "reza",
         "lastname": "razavi",
         "phone": "852125"
      },
      {
         "name": "hasan",
         "lastname": "hasani",
         "phone": "258008"
      },
      {
         "name": "hamid",
         "lastname": "hamedi",
         "phone": "2589631"
      },
      {
         "name": "neda",
         "lastname": "naderi",
         "phone": "214785"
      },
      {
         "name": "korosh",
         "lastname": "kordi",
         "phone": "258521"
      },
      {
         "name": "kazem",
         "lastname": "nbaloocji",
         "phone": "258745"
      }
   ]

در اندروید استودیو یک پوشه از نوع raw ایجاد می کنیم و فایل را در آن کپی می کنیم. پوشه raw بصورت زیر ساخته می شود:

ایجاد دایرکتوری raw

سپس باید کلاسی برای مدل کردن محتوای فایل JSON ایجاد کنیم. در نتیجه سه صفت name lastname و phone را ایجاد می کنیم. سپس متدهای سازنده و getter و setter آنرا میسازیم:

public class Contact {
    private String title;
    private String phone1;
    private String phone2;

    public Contact(String title, String phone1, String phone2) {
        this.title = title;
        this.phone1 = phone1;
        this.phone2 = phone2;
    }

    public Contact() {
    }

    public String getTitle() {
        return title;
    }

    public String getPhone1() {
        return phone1;
    }

    public String getPhone2() {
        return phone2;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setPhone1(String phone1) {
        this.phone1 = phone1;
    }

    public void setPhone2(String phone2) {
        this.phone2 = phone2;
    }

    public String toString(){
        return title+"    "+phone1+"\n"+"     "+phone2;
    }
}

متد toString برای نحوه نمایش در ابزار ListView است.

سپس یک کلاس دیگر ایجاد می کنیم با نام ContactJSONParser تا از طریق آن محتوای JSON را تجزیه و تحلیل کنیم. برای این منظور ابتدا یک متد با نام parseJSON‌ ایجاد می کنیم. خروجی این متد لیستی از آیتم هایی است که مطابق مدل کلاس Contact ایجاد شده اند:

public class ContactJSONParser {

    public List<Contact> parseJSON(String jsonString){
        List<Contact> contactList =new ArrayList<>();
        try {
            JSONArray jsonArray=new JSONArray(jsonString);
            for (int i=0;i<jsonArray.length();i++){

                JSONObject jsonObject=jsonArray.getJSONObject(i);
                Contact contact=new Contact();
                contact.setTitle(jsonObject.getString("name"));
                contact.setPhone1(jsonObject.getString("lastname"));
                contact.setPhone2(jsonObject.getString("phone"));
                contactList.add(contact);
                Log.i("json","OK");
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return contactList;
    }

همانطوریکه مشاهده می شود ورودی متد parseJSON یک رشته با نام jsonString است. این رشته همان محتوای فایل contact.json‌ است. از آنجاییکه محتوای فایل از نوع stream است آنرا به کمک متد convertInputStream2String به رشته تبدیل می کنیم. ورودی این تابع از نوع InputStream است و خروجی آن از نوع String است. کد آن در زیر آمده است:

 public String convertInputStream2String(InputStream inputStream) throws IOException {
        StringBuilder stringBuilder=new StringBuilder();
        BufferedInputStream bufferedInputStream=new BufferedInputStream(inputStream);
        while (bufferedInputStream.available()!=0){
            stringBuilder.append((char)bufferedInputStream.read());
        }
        bufferedInputStream.close();
        return stringBuilder.toString();
    }

برای ساخت رشته از کلاس StringBuilder استفاده می شود و محتوا هر دفعه در بافر (BufferInputStream) ذخیره می شود و تا زمانی که به انتهای فایل نرسیده به رشته stringBuilder اضافه می شود. رشته ساخته شده خروجی این متد است. محتوای کامل کلاس ContactJSONPaser در زیر آمده است:

public class ContactJSONParser {

    public List<Contact> parseJSON(String jsonString){
        List<Contact> contactList =new ArrayList<>();
        try {
            JSONArray jsonArray=new JSONArray(jsonString);
            for (int i=0;i<jsonArray.length();i++){

                JSONObject jsonObject=jsonArray.getJSONObject(i);
                Contact contact=new Contact();
                contact.setTitle(jsonObject.getString("name"));
                contact.setPhone1(jsonObject.getString("lastname"));
                contact.setPhone2(jsonObject.getString("phone"));
                contactList.add(contact);
                Log.i("json","OK");
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return contactList;
    }

    public String convertInputStream2String(InputStream inputStream) throws IOException {
        StringBuilder stringBuilder=new StringBuilder();
        BufferedInputStream bufferedInputStream=new BufferedInputStream(inputStream);
        while (bufferedInputStream.available()!=0){
            stringBuilder.append((char)bufferedInputStream.read());
        }
        bufferedInputStream.close();
        return stringBuilder.toString();
    }
}

حال به mainActivity.xml میرویم و یک ListView در آن قرار می دهیم. کد این فایل به صورت زیر آمده است:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/list"/>


</LinearLayout>

در ادامه به MainActivity.java میرویم و ابتدا محتوای فایل contact.json را می خوانیم:

 InputStream inputStream=getResources().openRawResource(R.raw.newjson);

سپس محتوا با فراخوانی متد convertStream2String به رشته تبدیل می شود. رشته برای متد parseJSON‌ ارسال می شود. با تجزیه تحلیل رشته ورودی در لیست قرار می گیرد این لیست contacts نام دارد و بصورت عمومی بصورت زیر تعریف می شود:

 private List<Contact> contacts;

کد مربوط به تبدیل محتوای فایل به لیست بصورت زیر آمده است:

ContactJSONParser contactJSONParser=new ContactJSONParser();
       
 String contentFile= contactJSONParser.convertInputStream2String(inputStream);
Toast.makeText(this, contentFile, Toast.LENGTH_SHORT).show();
contacts=contactJSONParser.parseJSON(contentFile);
Toast.makeText(this, "Number of contacts: "+contacts.size(), Toast.LENGTH_SHORT).show();

در ادامه باید محتوای لیست contacts را در لیست نمایش داد. برای این منظور یک متد جدید در MainActivity ایجاد می کنیم که نام آن dispaly است:

 public void Display(){
        adapter=new ArrayAdapter<Contact>(this,android.R.layout.simple_list_item_1,contacts);
        listView.setAdapter(adapter);
    }

متغیر adapter نیز به صورت عمومی از نوع ArrayAdapter بصورت زیر تعریف می شود:

 private ArrayAdapter<Contact> adapter;

کد کامل کلاس MainActivity بصورت زیر است:

public class MainActivity extends AppCompatActivity {

    private List<Contact> contacts;
    ListView listView;
    private ArrayAdapter<Contact> adapter;

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

        listView=findViewById(R.id.list);
        InputStream inputStream=getResources().openRawResource(R.raw.newjson);
        ContactJSONParser contactJSONParser=new ContactJSONParser();
        try {
            String contentFile= contactJSONParser.convertInputStream2String(inputStream);
            Toast.makeText(this, contentFile, Toast.LENGTH_SHORT).show();
            contacts=contactJSONParser.parseJSON(contentFile);
            Toast.makeText(this, "Number of contacts: "+contacts.size(), Toast.LENGTH_SHORT).show();
            Display();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void Display(){
        adapter=new ArrayAdapter<Contact>(this,android.R.layout.simple_list_item_1,contacts);
        listView.setAdapter(adapter);
    }


}

با اجرای برنامه خروجی به صورت زیر نشان داده می شود:

جهت بدست آوردن اندازه صفحه نمایش از کلاس Display استفاده می کنیم. علاوه براین باید معیار اندازه را نیز با DisplayMetrics بدست آوریم. با توجه به اینکه اندازه و کیفیت تصویر(رزولوشن) هر دو باید در نظر گرفته شوند در نتیجه از متد density هم باید استفاده کرد. نحوه استفاده از این کلاس ها و متدها به صورت زیر است:

Display display=this.getWindowManager().getDefaultDisplay();
        DisplayMetrics metrics=new DisplayMetrics();
        display.getMetrics(metrics);
        float density=this.getResources().getDisplayMetrics().density;

حال برای بدست آوردن طول و عرض صفحه نمایش از متغیرهای dpWidth و dpHeight استفاده می شود:

dpWidth=metrics.widthPixels/density;
        dpHeight=metrics.heightPixels/density;

جهت نمایش طول و عرض ابتدا یک منو بصورت زیر ایجاد می کنیم و نام آنرا dimensions قرار می دهیم:

public boolean onCreateOptionsMenu(Menu menu) {
        menu.add("dimensions").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem menuItem) {
                //Toast.makeText(MainActivity.this, "aaa", Toast.LENGTH_SHORT).show();
                showDimension();
                return false;
            }
        });
        return super.onCreateOptionsMenu(menu);
    }

سپس تابع showDimension بصورت زیر تعریف می شود:

 private void showDimension() {
        Display display=this.getWindowManager().getDefaultDisplay();
        DisplayMetrics metrics=new DisplayMetrics();
        display.getMetrics(metrics);
        float density=this.getResources().getDisplayMetrics().density;
        float dpWidth,dpHeight;
        dpWidth=metrics.widthPixels/density;
        dpHeight=metrics.heightPixels/density;
        Toast.makeText(this, "Width is: "+dpWidth+", Height is: "+dpHeight, Toast.LENGTH_LONG).show();
        //return dpWidth;
    }

حال با اجرای برنامه و انتخاب منوی dimensions نتیجه برای یک تبلت به صورت زیر است:

نمایش Toast برای ابعاد صفحه نمایش

حال قصد داریم در مثالی همانطوریکه در شکل بالا مشاهده می شود برنامه ابعاد متفاوت صفحه نمایش را تشخیص دهد و براساس آن تک ستونه و دو ستونه باشد. چنانچه پهنا کمتر از ۶۰۰ بود تک ستونه باشد و فقط لیست ویو نمایش داده شود و در غیر اینصورت دوستونه باشد و مانند شکل بالا روی هر آیتم لیست که کلیک شد جزییات در کنار آن نشان داده شود. این مثال ادامه ی برنامه بانک اطلاعاتی است. برای این منظور ابتدا یک پوشه جدید در layout با نام layout-sw600dp ایجاد می کنیم و در پوشه ساخته شده فایل mainactivity.xml را کپی می کنیم. باید نتیجه به صورت زیر شود:

چند mainactivity.xml

به فایل mainActivity.xml‌ در پوشه ی layout-sw600dp رفته و کد به صورت زیر تغییر میابد:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    tools:context="ir.faratez.msession5.MainActivity">
    <FrameLayout
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Large screen"
            android:layout_gravity="center"
            android:gravity="center"/>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:weightSum="10">

            <ImageView
                android:id="@+id/imageView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                app:srcCompat="@android:drawable/sym_def_app_icon" />

            <EditText
                android:id="@+id/edt_name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="9"
                android:ems="10"
                android:hint="Name"
                android:inputType="textPersonName" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:weightSum="10">

            <ImageView
                android:id="@+id/imageView2"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_marginLeft="10dp"
                android:layout_weight="1.75"
                android:background="@android:color/darker_gray"
                app:srcCompat="@android:drawable/stat_sys_speakerphone" />

            <EditText
                android:id="@+id/edt_phone"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="5dp"
                android:layout_weight="6.89"
                android:ems="10"
                android:hint="Phone"
                android:inputType="phone" />
        </LinearLayout>

        <Button
            android:id="@+id/btn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:gravity="center"
            android:text="ذخیره" />

        <ListView
            android:id="@+id/list"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </FrameLayout>
    <FrameLayout
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent">
        <LinearLayout
            android:layout_marginTop="250dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center
"               android:gravity="center"
                android:text="aaa"
                android:id="@+id/tv_larges_id"/>
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="70dp"
                android:layout_gravity="center
"               android:gravity="center"
                android:text="bbb"
                android:id="@+id/tv_larges_name"/>

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="70dp"
                android:layout_gravity="center
"               android:gravity="center"
                android:text="ccc"
                android:id="@+id/tv_larges_phone"/>
        </LinearLayout>
    </FrameLayout>
</LinearLayout>

سپس به کلاس Database میرویم و متد getId را اضافه می کنیم:

public String[] getId(String name,String phone){
        SQLiteDatabase db=getWritableDatabase();
        String q="select * from "+myTable +" where name='"+ name+"' and phone='"+phone+"'";
        Cursor cursor= db.rawQuery(q,null);
        String[] r=new String[1];

            cursor.moveToFirst();
            r[0]=cursor.getString(0);

        db.close();
        return r;
    }

سپس به MainActivity میرویم و کد زیر را در متد getView ادامه کدهای قبل می نویسیم.

 row.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    String[] id=dbHelper.getId(tv_name.getText().toString(),tv_phone.getText().toString());
                    //Toast.makeText(MainActivity.this, id[0], Toast.LENGTH_SHORT).show();

مجدد به کلاس DataBase می رویم و متد getDetails را به صورت زیر می نویسیم:

 public  String[] getDetails(String id){
        SQLiteDatabase db=getWritableDatabase();
        String q="select * from "+myTable +" where id='"+ id+"'";
        Cursor cursor= db.rawQuery(q,null);
        String[] r=new String[3];

        cursor.moveToFirst();
        r[0]=cursor.getString(0);
        r[1]=cursor.getString(1);
        r[2]=cursor.getString(2);

        db.close();
        return r;


    }

در ادامه مجدد به MainActitvity‌برگشته و کدر زیر را در آن مینویسیم:

 String[] d;
                    d=dbHelper.getDetails(id[0]);
                    //Toast.makeText(MainActivity.this, d[0]+" "+d[1], Toast.LENGTH_SHORT).show();
                    float w=showDimension();

همانطوریکه مشاهده می شود تابع showDimension مقدار اعشاری برمیگرداند که به صورت زیر تغییر کرده است:

 private float showDimension() {
        Display display=this.getWindowManager().getDefaultDisplay();
        DisplayMetrics metrics=new DisplayMetrics();
        display.getMetrics(metrics);
        float density=this.getResources().getDisplayMetrics().density;
        float dpWidth,dpHeight;
        dpWidth=metrics.widthPixels/density;
        dpHeight=metrics.heightPixels/density;
        //Toast.makeText(this, "Width is: "+dpWidth+", Height is: "+dpHeight, Toast.LENGTH_LONG).show();
        return dpWidth;
    }

حال وقت آن است که برطبق مقدار w (عرض صفحه نمایش) نمایش برنامه متفاوت باشد. پس به صورت زیر کد مربوط به نمایش در w>600 (تبلت ) را می نویسیم:

if (w>600){
                        //Toast.makeText(MainActivity.this, "Large Screen", Toast.LENGTH_SHORT).show();
                        tv_large_id.setText("ID is: " + d[0]);
                        tv_large_name.setText("Name is: " + d[1]);
                        tv_large_phone.setText("Phone is: " + d[2]);




                    }

سپس نوبت به صفحه نمایش ها با عرض کوچک می رسد در این حالت با انتخاب هر آیتم از لیست به اکتیویتی دیگر می رود:

else{
                        Toast.makeText(MainActivity.this, "Small Screen", Toast.LENGTH_SHORT).show();
                        Intent intent =new Intent(MainActivity.this,MainActivity2.class);
                        intent.putExtra("id",d[0]);
                        intent.putExtra("name",d[1]);
                        intent.putExtra("phone",d[2]);
                        startActivity(intent);
                    }

اکتیویتی بعدی مربوط به صفحه نمایش های کوچک به صورت زیر است:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:layout_marginTop="250dp"
    tools:context=".MainActivity2">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center
"               android:gravity="center"
        android:text="aaa"
        android:id="@+id/tv_smalls_id"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="70dp"
        android:layout_gravity="center
"               android:gravity="center"
        android:text="bbb"
        android:id="@+id/tv_smalls_name"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="70dp"
        android:layout_gravity="center
"               android:gravity="center"
        android:text="ccc"
        android:id="@+id/tv_smalls_phone"/>

</LinearLayout>
public class MainActivity2 extends AppCompatActivity {
    TextView tv_small_id,tv_small_name,tv_small_phone;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        tv_small_id=findViewById(R.id.tv_smalls_id);
        tv_small_name=findViewById(R.id.tv_smalls_name);
        tv_small_phone=findViewById(R.id.tv_smalls_phone);
        Bundle b=getIntent().getExtras();
        String id=b.getString("id");
        tv_small_id.setText("ID is: "+id);
        String name=b.getString("name");
        tv_small_name.setText("Name is: "+name);
        String phone=b.getString("phone");
        tv_small_phone.setText("Phone is: "+phone);

    }
}

بانک اطلاعاتی که در اندروید استودیو از آن استفاده می شود SQLite نام دارد که برای استفاده از آن باید کلاسی ایجاد کرد که از کلاس SQLiteOpenHelper مشتق شود.

public class Database extends SQLiteOpenHelper {

کلاس ایجاد شده باید دارای متدهای سازنده، () onCreate و () onUpgrade باشد. چنانچه قصد ایجاد یک بانک اطلاعاتی داریم باید ابتدا نام آنرا در یک متغیر ذخیره کنیم و در بخش super سازنده به همراه شماره ورژن آن معرفی شود. نام جدول نیز در متغیری ذخیره می شود. دستور ایجاد جدول جدید در یک متغیر رشته ای به صورت زیر تعریف می شود.

private String sqlTable="CREATE TABLE "+ myTable +"(" +
            "  [id] INT PRIMARY KEY NOT NULL UNIQUE," +
            "  [name] TEXT, " +
            "  [phone] TEXT)";

همانطوریکه مشاهده می شود نام جدول در متغیر myTable است و جدول دارای سه فیلد id ، name و field است. اجرای کد فوق در متد () onCreate انجام می شود که از تابع execSql استفاده می شود. کد کامل مطالب گفته شده به صورت زیر است:

public class Database extends SQLiteOpenHelper {
    private static final String dbName="myDb";
    private static final String myTable="myTable";
    private String sqlTable="CREATE TABLE "+ myTable +"(" +
            "  [id] INT PRIMARY KEY NOT NULL UNIQUE," +
            "  [name] TEXT, " +
            "  [phone] TEXT)";

    public Database(Context context) {
        super(context, dbName, null, 1);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(sqlTable);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }

حال جهت اجرا به کلاس mainActivity میرویم و در متد () onCreate کد زیر را می نویسیم.

SQLiteDatabase db=dbHelper.getWritableDatabase();
        if (db.isOpen()){
            db.close();
            Log.i("db","OK");
        }

جهت درج رکورد جدید ابتدا فرمی برای دریافت اطلاعات ایجاد می کنیم. که کد xml آن به صورت زیر آمده است.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="ir.faratez.msession5.MainActivity">


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:weightSum="10">

        <ImageView
            android:id="@+id/imageView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            app:srcCompat="@android:drawable/sym_def_app_icon" />

        <EditText
            android:id="@+id/edt_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="9"
            android:ems="10"
            android:hint="Name"
            android:inputType="textPersonName" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:weightSum="10">

        <ImageView
            android:id="@+id/imageView2"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_marginLeft="10dp"
            android:layout_weight="1.75"
            android:background="@android:color/darker_gray"
            app:srcCompat="@android:drawable/stat_sys_speakerphone" />

        <EditText
            android:id="@+id/edt_phone"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5dp"
            android:layout_weight="6.89"
            android:ems="10"
            android:hint="Phone"
            android:inputType="phone" />
    </LinearLayout>

    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:gravity="center"
        android:text="ذخیره" />

    <ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

ابزار listView که در پایین قرار گرفته برای قسمت بعد می باشد که قصد نمایش اطلاعات را داریم.

حال جهت درج رکورد جدید به کلاس database میرویم و متدی با نام دلخواه insert2Table در آن به صورت زیر ایجاد می کنیم:

public void insert2Table(String name, String phone){

        SQLiteDatabase db=getWritableDatabase();
        String q="select * from "+myTable;
        Cursor cursor= db.rawQuery(q,null);
        ContentValues cv=new ContentValues();
        cv.put("name",name);
        cv.put("phone",phone);
        cv.put("id",cursor.getCount()+1);
        Long insertId= db.insert(myTable,null,cv);

        Log.i("id","inserted: "+insertId);
        db.close();
    }

در ادامه به mainActivity میرویم و ابتدا عناصر را به صورت عمومی معرفی می کنیم:

Database dbHelper;
    EditText edtName,edtPhone;
    Button btn;

سپس آنها را در onCreate تعریف می کنیم:

edtName= (EditText) findViewById(R.id.edt_name);
        edtPhone= (EditText) findViewById(R.id.edt_phone);
        btn= (Button) findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String n="",p="";
                n=edtName.getText().toString();
                p=edtPhone.getText().toString();
                //Toast.makeText(MainActivity.this, n+"\n "+p, Toast.LENGTH_SHORT).show();
                dbHelper.insert2Table(n,p);
                Toast.makeText(MainActivity.this, "Inserted!", Toast.LENGTH_SHORT).show();
               
            }
        });

برنامه را اجرا کنید داده وارد کنید و بررسی کنید اضافه شده یا خیر.

جهت نمایش اطلاعات درج شده ابتدا باید برای listView یک لایه بسازیم. برای این منظور در لایه جدیدی در پوشه Layout این کار انجام می شود:

<TextView
    android:id="@+id/tvName"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="TextView"
    android:textColor="@android:color/background_dark"
    android:textSize="24sp" />

<TextView
    android:id="@+id/tvPhone"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="15dp"
    android:text="TextView"
    android:textSize="18sp" />

پس از افزودن لایه باید جهت نمایش تمام اطلاعات به کلاس database برویم و متد با نام دلخواه getFullList در آن ایجاد می کنیم:

public String[][] getFullList(){
        SQLiteDatabase db=getWritableDatabase();
        String q="select * from "+myTable;
        Cursor cursor= db.rawQuery(q,null);
        String[][] r=new String[3][cursor.getCount()];
        for (int i=0;i<cursor.getCount();i++){
            cursor.moveToPosition(i);
            r[1][i]=cursor.getString(1);
            r[2][i]=cursor.getString(2);
        }

        db.close();
        return r;

    }

سپس یک متغیر آرایه دوبعدی برای نگهداری رکوردهای بازیابی شده عمومی تعریف می کنیم:

String[][] res;

سپس به MainActivity می رویم و خارج از oncreate در کلاس MainActivity یک کلاس دیگر تعریف می کنیم.

class AA extends ArrayAdapter<String>{

        public AA() {
            super(MainActivity.this, R.layout.a_row_of_list,res[0]);
        }

        @NonNull
        @Override
        public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
            LayoutInflater in=getLayoutInflater();
            View row=in.inflate(R.layout.a_row_of_list,parent,false);
            TextView tv_name= (TextView) row.findViewById(R.id.tvName);
            TextView tv_phone= (TextView) row.findViewById(R.id.tvPhone);
            tv_name.setText(res[1][position]);
            tv_phone.setText(res[2][position]);
            return row;
        }
    }

جهت اجرا در onCreate کد زیر را می نویسیم:

res=dbHelper.getFullList();
        list= (ListView) findViewById(R.id.list);
        list.setAdapter(new AA());

جهت نمایش رکورد جدید اضافه شده به جدول در لیست کد زیر را به onClick دکمه اضافه می کنیم:

res=dbHelper.getFullList();
                
                list.setAdapter(new AA());

کد کلاس MainActivity به صورت زیر است:

package ir.faratez.msession5;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    Database dbHelper;
    EditText edtName,edtPhone;
    Button btn;
    String[][] res;
    ListView list;

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

        dbHelper=new Database(this);
        SQLiteDatabase db=dbHelper.getWritableDatabase();
        if (db.isOpen()){
            db.close();
            Log.i("db","OK");
        }
        

        res=dbHelper.getFullList();
        list= (ListView) findViewById(R.id.list);
        list.setAdapter(new AA());
	edtName= (EditText) findViewById(R.id.edt_name);
        edtPhone= (EditText) findViewById(R.id.edt_phone);
        btn= (Button) findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String n="",p="";
                n=edtName.getText().toString();
                p=edtPhone.getText().toString();
                //Toast.makeText(MainActivity.this, n+"\n "+p, Toast.LENGTH_SHORT).show();
                dbHelper.insert2Table(n,p);
                Toast.makeText(MainActivity.this, "Inserted!", Toast.LENGTH_SHORT).show();
                res=dbHelper.getFullList();
                
                list.setAdapter(new AA());
            }
        });
    }

    class AA extends ArrayAdapter<String>{

        public AA() {
            super(MainActivity.this, R.layout.a_row_of_list,res[0]);
        }

        @NonNull
        @Override
        public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
            LayoutInflater in=getLayoutInflater();
            View row=in.inflate(R.layout.a_row_of_list,parent,false);
            TextView tv_name= (TextView) row.findViewById(R.id.tvName);
            TextView tv_phone= (TextView) row.findViewById(R.id.tvPhone);
            tv_name.setText(res[1][position]);
            tv_phone.setText(res[2][position]);
            return row;
        }
    }
}

درس بعدی | | | | | درس قبلی

‌Broadcast receiver به سادگی به پیام های پخش شده از برنامه های دیگر یا از خود سیستم پاسخ می دهند. این پیام ها گاهی اوقات رویدادها یا اهداف نامیده می شوند. به عنوان مثال ، برنامه ها همچنین می توانند پخش را آغاز کنند تا سایر برنامه ها بدانند که برخی از داده ها در دستگاه بارگیری شده اند و برای آنها در دسترس است ، بنابراین این گیرنده پخش است که این ارتباط را رهگیری کرده و اقدامات مناسب را آغاز می کند.

برای ایجاد BroadcastReceiver برای اهداف پخش شده در سیستم ، دو مرحله مهم وجود دارد –

ایجاد ‌Broadcast Receiver

ثبت Broadcast Receiver

اگر بخواهید اهداف دلخواه خود را پیاده سازی کنید ، یک مرحله دیگر وجود دارد ، شما مجبورید آن اهداف را ایجاد و پخش کنید.

ایجاد ‌Broadcast Receiver
یک گیرنده پخش به عنوان یک زیر کلاس از کلاس BroadcastReceiver و ایجاد متد onReceive (که هر پیام به عنوان یک پارامتر شی object Intent دریافت می شود) پیاده سازی می شود.

public class MyReceiver extends BroadcastReceiver {
   @Override
   public void onReceive(Context context, Intent intent) {
     ...
   }
}

ثبت Broadcast Receiver

برای نسخه های اندروید کمتر از ۷ کافی است تنظیمات به صورت زیر در مانیفست (manifest.xml) انجام شود. ما قصد داریم برنامه ای بنویسیم که اپلکیشن از فعال و غیر فعال شدن اینترنت با خبر شود.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="ir.faratez.msession4">

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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


        <receiver android:name=".Mybroadcast">
            <intent-filter>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
            </intent-filter>
        </receiver>
    </application>

</manifest>

همانطوریکه مشاهده می شود ابتدا یک سطح دسترسی برای وضعیت شبکه دریافت شده است که کد آن در زیر آمده است:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

در دستور receiver برادکسترسیور ثبت می شود. کلاس Mybroadcast که قبلا ایجاد شده است معرفی شده است و در دستور receiver این کلاس جهت بررسی تغییرات اتصال ثبت شده است.

<receiver android:name=".Mybroadcast">
            <intent-filter>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
            </intent-filter>
        </receiver>

به کلاس Mybroadcast برمیگردیم. جهت بررسی وضعیت شبکه تابع () checkNetwork را نوشتیم. کد آن بصورت زیر است:

    private boolean checkNetwork(Context mContext){
        try {
            ConnectivityManager conManager= (ConnectivityManager)
                    mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo nInfo=conManager.getActiveNetworkInfo();
            if (nInfo.isConnected()){
                return true;
            }else{
                return false;
            }
        }catch (NullPointerException e){
            return false;
        }


    }

توسط متد ConnectivityManager و سپس ()getActiveNetworkInfo وضعیت اتصال بررسی شده و نتیجه در nInfo ذخیره می‌شود. متد از نوع boolean بوده و قرار است یک نتیجه true یا false برگرداند. سپس با دستور زیر تعیین می شود اتصال برقرار است یا خیر.

if (nInfo.isConnected()){
                return true;
            }else{
                return false;
            }

در رویداد () onReceive کد زیر را می نویسیم تا با تغییر وضعیت شبکه یک پیغام به کاربر نمایش دهد.

 public void onReceive(Context context, Intent intent) {
        if (checkNetwork(context)){
            Toast.makeText(context, "اتصال به شبکه برقرار است", Toast.LENGTH_SHORT).show();
        }else {
            Toast.makeText(context, "اتصال برقرار نیست", Toast.LENGTH_SHORT).show();
        }
    }

به کلاس MainActivity میرویم. چنانچه نسخه اندروید بالای ۷ باشد مجدد در متد onResume باید برادکست رسیور ثبت شود. بنابراین اول تعیین میشود نسخه اندروید چند است و اگر بالای ۲۴ (اندروید ۷ یا بالاتر) بود ثبت می شود. به صورت زیر:

@Override
    protected void onResume() {
        if (Build.VERSION.SDK_INT>Build.VERSION_CODES.N){
            myBroadcast=new Mybroadcast();
            registerReceiver(myBroadcast,new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE"));
        }
        super.onResume();
    }

جهت جلوگیری از بروز خطا باید در رویداد onPause عدم ثبت انجام شود. کد آن بصورت زیر است.

 @Override
    protected void onPause() {
        unregisterReceiver(myBroadcast);
        super.onPause();
    }

برنامه را اجرا می کنیم با فعال و غیرفعال کردن Wifi پیغام Toast نمایش داده می شود.

آموزش قبلی | | | | | آموزش بعدی

سرویس بخشی است که برای انجام عملیات طولانی مدت بدون نیاز به تعامل با کاربر در پس زمینه اجرا می شود و حتی اگر برنامه از بین برود نیز کار می کند. یک سرویس اساساً می تواند دو حالت داشته باشد.

۱شروع شده

زمانی سرویس شروع می شود که یک جز application برنامه ، مانند یک فعالیت ، با فراخوانی startService () آن را شروع کند. با شروع کار ، یک سرویس می تواند به صورت نامحدود در پس زمینه اجرا شود ، حتی اگر جز component شروع کننده آن از بین برود.

۲ محدود شده

وقتی یک   component برنامه با فراخوانی ()bindService به آن متصل می شود، سرویس محدود می شود. یک سرویس محدود یک رابط سرویس گیرنده و سرور را ارائه می دهد که به اجزای سازنده امکان می دهد با سرویس ارتباط برقرار کنند ، درخواست ارسال کنند ، نتیجه بگیرند و حتی این کار را در فرایندهای دارای ارتباط بین پردازش (IPC) انجام دهند. یک سرویس دارای روشهای برگشت چرخه عمر است که می توانید برای نظارت بر تغییرات وضعیت سرویس ، آنها را پیاده سازی کنید و می توانید کارها را در مرحله مناسب انجام دهید.

نمودار زیر سمت چپ ، چرخه زندگی را هنگام ایجاد سرویس با ()startService نشان می دهد و نمودار سمت راست ، چرخه زندگی را هنگام ایجاد سرویس با ()bindService نشان می دهد.

چرخه عمر سرویس ها در اندروید

برای ایجاد یک سرویس ، شما یک کلاس جاوا ایجاد می کنید که کلاس پایه سرویس یا یکی از زیر کلاس های موجود آن را گسترش می دهد. کلاس پایه Service روشهای مختلفی برای پاسخگویی را تعریف می کند و مهمترین آنها در زیر آورده شده است. نیازی به پیاده سازی همه روش های برگشت تماس نیست. با این حال ، مهم این است که شما هر یک را بفهمید و مواردی را که برنامه شما را مطابق انتظار کاربران تضمین می کند ، اجرا کنید.

۱ در()StartCommand

این سیستم وقتی متغیر دیگری مانند یک فعالیت با شروع تماس () startService درخواست راه اندازی سرویس را می کند ، این روش را فراخوانی می کند. اگر این روش را اجرا کنید ، وظیفه شماست که با پایان دادن به کار سرویس ، با فراخوانی روش های stopSelf () یا stopService () خدمات را متوقف کنید.

۲ ()onBind

این سیستم زمانی متد را فراخوانی می کند که component دیگری با فراخوانی ()bindService به سرویس بپیوندد. اگر این روش را پیاده سازی کنید ، باید با بازگرداندن یک شی IB IBinder ، رابطی ارائه دهید که کاربران از آن برای ارتباط با سرویس استفاده می کنند. شما همیشه باید این روش را پیاده سازی کنید ، اما اگر نمی خواهید اجازه اتصال دهید ، باید صفر برگردانید. که ما صفر برمی گردانیم.

۳ ()onUnbind

این سیستم وقتی این روش را فراخوانی می کند که همه سرویس گیرنده ها از یک رابط خاص منتشر شده توسط سرویس جدا شوند.

۴ ()onRebind

این سیستم زمانی متصل می شود که سرویس گیرنده های جدید به سرویس متصل شده باشند ، پس از اینکه قبلاً به آن اطلاع داده شده بود که همه اتصال (onUnbind (Intent آن قطع شده است.

۵ ()onCreate

این سیستم وقتی اولین سرویس با استفاده از ()onStartCommand یا ()onBind ایجاد می شود ، این روش را فراخوانی می کند. این تماس برای انجام تنظیم یکبار مصرف لازم است.

۶ ()onDestroy

سیستم این روش را زمانی فراخوانی می کند که سرویس دیگر استفاده نشود و در حال تخریب باشد. سرویس شما باید این کار را برای پاک کردن منابع انجام دهد.

مثال
این مثال شما را با طی مراحل ساده هدایت می کند تا نحوه ایجاد سرویس Android خود را نشان دهید. مراحل زیر را دنبال کنید تا برنامه Android را که در فصل Hello World ایجاد کرده ایم اصلاح کنید.

شرح مرحله
۱ شما برای ایجاد یک برنامه Android از Android StudioIDE استفاده خواهید کرد و نام آن را به عنوان برنامه من تحت یک بسته com.example.tutorialspoint7.myapplication همانطور که در بخش سلام جهانی مثال توضیح داده شده است ، استفاده خواهید کرد.
۲ پرونده فعالیت اصلی MainActivity.java را برای افزودن روشهای ()startService و ()stopService تغییر دهید.
۳ یک فایل جاوا جدید ایجاد کنید MyService.java در زیر بسته com.example.My Application. این فایل از روش های مربوط به سرویس Android استفاده می کند.
۴ با استفاده از برچسب سرویس خود را در پرونده AndroidManifest.xml تعریف کنید. یک برنامه کاربردی می تواند یک یا چند سرویس بدون هیچ محدودیتی داشته باشد.
۵ محتوای پیش فرض فایل res / layout / activity_main.xml را تغییر دهید تا شامل دو دکمه در طرح خطی باشد.
۶ نیازی به تغییر ثابتها در پرونده res / values ​​/ strings.xml نیست.
۷ برای راه اندازی شبیه ساز Android و تأیید نتیجه تغییرات انجام شده در برنامه ، برنامه را اجرا کنید.
در زیر محتوای پرونده فعالیت اصلی تغییر یافته MainActivity.java است. این پرونده می تواند شامل هر یک از روشهای اساسی چرخه زندگی باشد. ما روش های ()startService و ()stopService را برای شروع و توقف سرویس اضافه کرده ایم.

package com.example.tutorialspoint7.myapplication;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.View;

public class MainActivity extends Activity {
   String msg = "Android : ";

   /** Called when the activity is first created. */
   @Override
   public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      Log.d(msg, "The onCreate() event");
   }

   public void startService(View view) {
      startService(new Intent(getBaseContext(), MyService.class));
   }

   // Method to stop the service
   public void stopService(View view) {
      stopService(new Intent(getBaseContext(), MyService.class));
   }
}

در زیر محتوای MyService.java است. این پرونده می تواند از یک یا چند روش مرتبط با سرویس بر اساس نیازها استفاده کند. در حال حاضر ما فقط دو روش را روی ()StartCommand و ()onDestroy پیاده سازی می کنیم.

package com.example.tutorialspoint7.myapplication;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.widget.Toast;

/**
   * Created by TutorialsPoint7 on 8/23/2016.
*/

public class MyService extends Service {
   @Nullable
   @Override
   public IBinder onBind(Intent intent) {
      return null;
   }
	
   @Override
   public int onStartCommand(Intent intent, int flags, int startId) {
      // Let it continue running until it is stopped.
      Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
      return START_STICKY;
   }

   @Override
   public void onDestroy() {
      super.onDestroy();
      Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
   }
}

در زیر محتوای اصلاح شده پرونده AndroidManifest.xml اعمال می شود. در اینجا ما برچسب را اضافه کرده ایم تا شامل سرویس ما شود.

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

   <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">
         <intent-filter>
            <action android:name="android.intent.action.MAIN" />

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

</manifest>

در زیر محتوای فایل res / layout / activity_main.xml وجود دارد که شامل دو دکمه است:

<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:paddingLeft="@dimen/activity_horizontal_margin"
   android:paddingRight="@dimen/activity_horizontal_margin"
   android:paddingTop="@dimen/activity_vertical_margin"
   android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
   
   <TextView
      android:id="@+id/textView1"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Example of services"
      android:layout_alignParentTop="true"
      android:layout_centerHorizontal="true"
      android:textSize="30dp" />
      
   <TextView
      android:id="@+id/textView2"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Tutorials point "
      android:textColor="#ff87ff09"
      android:textSize="30dp"
      android:layout_above="@+id/imageButton"
      android:layout_centerHorizontal="true"
      android:layout_marginBottom="40dp" />

   <ImageButton
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:id="@+id/imageButton"
      android:src="@drawable/abc"
      android:layout_centerVertical="true"
      android:layout_centerHorizontal="true" />

   <Button
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:id="@+id/button2"
      android:text="Start Services"
      android:onClick="startService"
      android:layout_below="@+id/imageButton"
      android:layout_centerHorizontal="true" />

   <Button
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Stop Services"
      android:id="@+id/button"
      android:onClick="stopService"
      android:layout_below="@+id/button2"
      android:layout_alignLeft="@+id/button2"
      android:layout_alignStart="@+id/button2"
      android:layout_alignRight="@+id/button2"
      android:layout_alignEnd="@+id/button2" />

</RelativeLayout>

بیایید سعی کنیم Hello World اصلاح شده خود را اجرا کنیم! برنامه ما فقط اصلاح شده است. من تصور می کنم شما AVD خود را هنگام راه اندازی محیط ایجاد کرده اید. برای اجرای برنامه از Android studio ، یکی از فایلهای فعالیت پروژه خود را باز کرده و از نوار ابزار روی نماد اجرای Android StudioRun Icon کلیک کنید. Android Studio برنامه را روی AVD شما نصب کرده و شروع به کار می کند و اگر با تنظیمات و برنامه هایتان همه چیز خوب باشد ، پس از پنجره شبیه ساز نمایش داده می شود:

خروجی برنامه

اکنون برای شروع سرویس خود ، بر روی دکمه Start Service کلیک کنید ، این سرویس شروع به کار می کند و طبق برنامه نویسی ما به روش()onStartCommand ، یک پیام Service Started در پایین شبیه ساز به شرح زیر ظاهر می شود:

درس بعدی |||||||| درس قبلی

یک Activity نشان دهنده یک صفحه منفرد با رابط کاربری است ، دقیقاً مانند پنجره یا قاب جاوا. فعالیت اندروید زیر کلاس کلاس ContextThemeWrapper است.
اگر با زبان برنامه نویسی C ، C ++ یا Java کار کرده باشید ، حتماً دیده اید که برنامه شما از تابع اصلی () شروع می شود. روشی کاملاً مشابه ، سیستم Android برنامه خود را با فعالیتی آغاز می کند که با فراخوانی روش پاسخگویی onCreate () شروع می شود. دنباله ای از روشهای پاسخ به تماس وجود دارد که یک فعالیت را راه اندازی می کند و دنباله ای از روشهای برگشت تماس که فعالیتی را از بین می برد همانطور که در نمودار چرخه حیات فعالیت زیر نشان داده شده است:

نمودار چرخه عمر اکتیویتی

کلاس Activity تماسهای زیر را به عنوان مثال رویدادها تعریف می کند. نیازی به پیاده سازی همه روش های برگشت تماس نیست. با این حال ، مهم این است که شما هر یک را بفهمید و مواردی را که برنامه شما را مطابق انتظار کاربران تضمین می کند ، اجرا کنید.

() onCreate
این اولین رویداد است و هنگام ایجاد فعالیت برای اولین بار فراخوانی می شود.
() onStart
این رویداد زمانی فراخوانی می شود که فعالیت برای کاربر قابل مشاهده شود.
() onResume
وقتی که کاربر شروع به تعامل با برنامه می کند.
() onPause
اکتیویتی Pause ورودی کاربر را دریافت نمی کند و نمی تواند هیچ کدی را اجرا کند و هنگامی که اکتیویتی فعلی در حالت Pause است و اکتیویتی قبلی از سر گرفته می شود فراخوانی می شود.
() onStop
زمانی فراخوانی می شود که اکتیویتی دیگر قابل مشاهده نباشد.
() onDestroy
این رویداد قبل از اینکه اکتیویتی توسط سیستم از بین برود فراخوانی می شود.
() onRestart
این رویداد با زمانی انجام می گیرد که اکتیویتی پس از متوقف شدن مجدداً شروع شود.

مثال
این مثال برای نشان دادن چرخه فعالیت فعالیت برنامه Android ، مراحل ساده ای را به شما ارائه می دهد. مراحل زیر را دنبال کنید تا برنامه Android را که در فصل Hello World mînak ایجاد کرده ایم اصلاح کنید:

۱-شما از Android studio برای ایجاد یک برنامه Android استفاده خواهید کرد و آن را به عنوان HelloWorld تحت یک بسته com.example.helloworld همانطور که در مثال سلام دنیا توضیح داده شده است ، نامگذاری کنید.

۲-همانطور که در زیر توضیح داده شده ، فایل اصلی فعالیت MainActivity.java را تغییر دهید. بقیه پرونده ها را بدون تغییر نگه دارید.

۳-برنامه را اجرا کنید تا شبیه ساز Android را راه اندازی کنید و نتیجه تغییرات انجام شده در برنامه را تأیید کنید.

در زیر محتوای پرونده فعالیت اصلی تغییر یافته src / com.example.helloworld / MainActivity.java است. این پرونده شامل هر یک از روشهای اساسی چرخه زندگی است. از روش Log.d () برای تولید پیام های ورود به سیستم استفاده شده است.

package com.example.helloworld;

import android.os.Bundle;
import android.app.Activity;
import android.util.Log;

public class MainActivity extends Activity {
   String msg = "Android : ";
   
   /** Called when the activity is first created. */
   @Override
   public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      Log.d(msg, "The onCreate() event");
   }

   /** Called when the activity is about to become visible. */
   @Override
   protected void onStart() {
      super.onStart();
      Log.d(msg, "The onStart() event");
   }

   /** Called when the activity has become visible. */
   @Override
   protected void onResume() {
      super.onResume();
      Log.d(msg, "The onResume() event");
   }

   /** Called when another activity is taking focus. */
   @Override
   protected void onPause() {
      super.onPause();
      Log.d(msg, "The onPause() event");
   }

   /** Called when the activity is no longer visible. */
   @Override
   protected void onStop() {
      super.onStop();
      Log.d(msg, "The onStop() event");
   }

   /** Called just before the activity is destroyed. */
   @Override
   public void onDestroy() {
      super.onDestroy();
      Log.d(msg, "The onDestroy() event");
   }
}

یک کلاس اکتیویتی با استفاده از فایل XML موجود در پوشه res / layout پروژه ، تمام م Uلفه UI را بارگیری می کند. عبارت زیر اجزای UI را از پرونده res / layout / activity_main.xml بارگیری می کند:

setContentView(R.layout.activity_main);

یک برنامه کاربردی می تواند یک یا چند فعالیت بدون هیچ محدودیتی داشته باشد. هر فعالیتی که برای برنامه خود تعریف می کنید باید در پرونده AndroidManifest.xml شما اعلام شود و فعالیت اصلی برنامه شما باید در مانیفست با که شامل MAIN action و LAUNCHER است به شرح زیر اعلام شود:

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

    <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">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>

اگر یکی از Activity اصلی یا LAUNCHER برای یکی از فعالیتهای شما اعلام نشده باشد ، نماد برنامه شما در لیست برنامه های صفحه اصلی ظاهر نمی شود.
بیایید سعی کنیم Hello World اصلاح شده خود را اجرا کنیم! برنامه ما فقط اصلاح شده است. من تصور می کنم شما AVD خود را هنگام راه اندازی محیط ایجاد کرده اید. برای اجرای برنامه از Android studio ، یکی از پرونده های فعالیت پروژه خود را باز کرده و از نوار ابزار روی Run icon کلیک کنید. Android studio برنامه را روی AVD شما نصب کرده و شروع به کار می کند و اگر با راه اندازی و برنامه همه چیز خوب است ، پنجره Emulator نمایش داده می شود و باید پیام های ورود به سیستم زیر را در پنجره LogCat در Android studio مشاهده کنید.

08-23 10:32:07.682 4480-4480/com.example.helloworld D/Android :: The onCreate() event
08-23 10:32:07.683 4480-4480/com.example.helloworld D/Android :: The onStart() event
08-23 10:32:07.685 4480-4480/com.example.helloworld D/Android :: The onResume() event
پنجره لاگ کت (Log CAT)

بیایید سعی کنیم دکمه قفل صفحه را روی شبیه ساز Android کلیک کنیم و پیام های زیر را در پنجره LogCat در android studio ایجاد می کند:

08-23 10:32:53.230 4480-4480/com.example.helloworld D/Android :: The onPause() event
08-23 10:32:53.294 4480-4480/com.example.helloworld D/Android :: The onStop() event

بیایید دوباره سعی کنیم قفل صفحه شما را روی شبیه ساز Android باز کنیم و پیام های زیر را در پنجره LogCat در Android studio ایجاد می کند:

08-23 10:34:41.390 4480-4480/com.example.helloworld D/Android :: The onStart() event
08-23 10:34:41.392 4480-4480/com.example.helloworld D/Android :: The onResume() event

در مرحله بعدی ، اجازه دهید دوباره سعی کنیم روی دکمه برگشت روی شبیه ساز Android کلیک کنیم و پیام های زیر را در پنجره LogCat در Android studio ایجاد می کند و این چرخه فعالیت Activity را برای یک برنامه Android تکمیل می کند.

08-23 10:37:24.806 4480-4480/com.example.helloworld D/Android :: The onPause() event
08-23 10:37:25.668 4480-4480/com.example.helloworld D/Android :: The onStop() event
08-23 10:37:25.669 4480-4480/com.example.helloworld D/Android :: The onDestroy() event

جلسه قبل جلسه بعد

موارد بسیاری وجود دارد که برای ساختن یک برنامه اندرویدی خوب از آنها استفاده می کنید. شما جدا از برنامه نویسی برای برنامه ، از منابع مختلف دیگری مانند محتوای استاتیک که کد شما از آن استفاده می کند ، مانند بیت مپ ، رنگ ، تعریف چیدمان ، رشته های رابط کاربر ، دستورالعمل های انیمیشن و غیره مراقبت می کنید. این منابع همیشه به طور جداگانه در زیر شاخه های مختلف تحت فهرست / فهرست پروژه نگهداری می شوند.
این آموزش به شما توضیح می دهد که چگونه می توانید منابع برنامه خود را سازماندهی کنید ، منابع جایگزین را مشخص کنید و در برنامه های خود به آنها دسترسی پیدا کنید.

سازماندهی منابع در Android Studio

MyProject/
   app/
      manifest/
         AndroidManifest.xml
   java/
      MyActivity.java  
      res/
         drawable/  
            icon.png  
         layout/  
            activity_main.xml
            info.xml
         values/  
            strings.xml 

1 anim/
پرونده های XML که انیمیشن های خاصیت را تعریف می کنند. آنها در پوشه res / anim / ذخیره می شوند و از کلاس R.anim به آنها دسترسی پیدا می شود.
2 color /
فایلهای XML که لیستی از رنگها را تعریف می کنند. آنها با رز / رنگ / ذخیره می شوند و از کلاس R.color قابل دسترسی هستند.
3 drawable/
پرونده های تصویری مانند .png ، .jpg ، .gif یا فایل های XML که در نقشه های بیت ، لیست های حالت ، اشکال ، انیمیشن قابل طراحی وارد می شوند آنها در res / drawable ذخیره می شوند و از کلاس R.drawable قابل دسترسی هستند.
4 layout /
پرونده های XML که طرح واسط کاربری را تعریف می کنند. آنها در res / layout ذخیره می شوند و از کلاس R.layout قابل دسترسی هستند.
5 menu/
پرونده های XML که منوهای برنامه را تعریف می کنند ، مانند منوی گزینه ها ، منوی زمینه یا زیر منو. آنها در res / menu / ذخیره می شوند و از کلاس R.menu قابل دسترسی هستند.
6 raw/
پرونده های خودسرانه برای ذخیره در فرم خام خود. برای باز کردن چنین پرونده های خام ، باید Resource.openRawResource () را با شناسه منبع که R.raw.filename است تماس بگیرید.
7 value /
پرونده های XML که حاوی مقادیر ساده ای مانند رشته ها ، اعداد صحیح و رنگ ها هستند. به عنوان مثال ، در اینجا برخی از قراردادهای نام فایل برای منابعی که می توانید در این فهرست ایجاد کنید وجود دارد –
• arrays.xml برای آرایه های منابع ، و از کلاس R.array قابل دسترسی است.
integers.xml برای اعداد صحیح منابع ، و از کلاس R.integer قابل دسترسی است.
• bools.xml برای منبع boolean و از کلاس R.bool قابل دسترسی است.
• colors.xml برای مقادیر رنگ ، و از کلاس R.color قابل دسترسی است.
• dimens.xml برای مقادیر ابعاد ، و از کلاس R.dimen قابل دسترسی است.
• strings.xml برای مقادیر رشته ، و از کلاس R.string قابل دسترسی است.
• styles.xml برای سبک ها ، و از کلاس R.style قابل دسترسی است.
8 xml /
پرونده های XML خودسرانه ای که در زمان اجرا با تماس با ()Resources.getXML قابل خواندن هستند. می توانید فایل های مختلف پیکربندی را که در زمان اجرا استفاده می شوند ، در اینجا ذخیره کنید.

منابع جایگزین

برنامه شما باید منابع جایگزینی را برای پشتیبانی از تنظیمات خاص دستگاه فراهم کند. به عنوان مثال ، شما باید منابع قابل جایگزینی قابل ترسیم (به عنوان مثال تصاویر) برای وضوح صفحه نمایش مختلف و منابع رشته ای جایگزین برای زبانهای مختلف داشته باشید. هنگام اجرا ، Android پیکربندی دستگاه فعلی را شناسایی کرده و منابع مناسب برنامه شما را بارگیری می کند.
برای تعیین گزینه های خاص پیکربندی برای مجموعه ای از منابع ، مراحل زیر را دنبال کنید –
• یک دایرکتوری جدید در res / به نام – ایجاد کنید. در اینجا منابع_ نام یکی از منابع ذکر شده در جدول فوق است ، مانند طرح بندی ، قابل ترسیم و غیره. مقدماتی یک پیکربندی منفرد را تعیین می کند که این منابع برای آن استفاده می شود. می توانید اسناد رسمی را برای لیست کاملی از واجد شرایط برای انواع مختلف منابع بررسی کنید.
• منابع جایگزین مربوطه را در این فهرست جدید ذخیره کنید. پرونده های منبع باید دقیقاً مانند پرونده های منبع پیش فرض همانطور که در مثال زیر نشان داده شده است ، نامگذاری شوند ، اما این پرونده ها محتوای خاص جایگزین دارند. به عنوان مثال اگرچه نام فایل تصویر یکسان خواهد بود اما برای صفحه نمایش با وضوح بالا ، وضوح آن زیاد خواهد بود.

در زیر مثالی آورده شده است که تصاویر را برای صفحه پیش فرض و تصاویر جایگزین را برای صفحه با وضوح بالا مشخص می کند.

MyProject/
   app/
      manifest/
         AndroidManifest.xml
   java/
      MyActivity.java   
      res/
         drawable/  
            icon.png
            background.png
         drawable-hdpi/  
            icon.png
            background.png  
         layout/  
            activity_main.xml
            info.xml
         values/  
            strings.xml 

در زیر نمونه دیگری وجود دارد که طرح بندی را برای یک زبان پیش فرض و طرح جایگزین را برای زبان عربی مشخص می کند.

MyProject/
   app/
      manifest/
         AndroidManifest.xml
   java/
      MyActivity.java   
      res/
         drawable/  
            icon.png
            background.png
         drawable-hdpi/  
            icon.png
            background.png  
         layout/  
            activity_main.xml
            info.xml
         layout-ar/
            main.xml
         values/  
            strings.xml 

دسترسی به منابع
در طول توسعه برنامه شما باید به منابع تعریف شده یا در کد خود ، یا در فایلهای XML طرح خود دسترسی پیدا کنید. بخش زیر نحوه دستیابی به منابع خود را در هر دو سناریو توضیح می دهد –
دسترسی به منابع در کد
هنگامی که برنامه Android شما کامپایل می شود ، یک کلاس R تولید می شود که شامل شناسه منابع برای تمام منابع موجود در فهرست / فهرست شما است. با استفاده از زیر شاخه و نام منبع یا به طور مستقیم شناسه منبع می توانید از کلاس R برای دسترسی به این منبع استفاده کنید.
مثال
برای دسترسی به res / drawable / myimage.png و تنظیم ImageView از کد زیر استفاده خواهید کرد –

ImageView imageView = (ImageView) findViewById(R.id.myimageview);
imageView.setImageResource(R.drawable.myimage);

در اینجا خط اول کد از R.id.myimageview استفاده می کند تا ImageView را با id myimageview در یک فایل Layout تعریف کند. خط دوم کد از R.drawable.myimage استفاده می کند تا تصویری با نام myimage در زیر شاخه قابل طراحی تحت / res دریافت کند.

مثال
مثال بعدی را در نظر بگیرید که در آن res / values / strings.xml تعریف زیر را دارد:

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <string  name="hello">Hello, World!</string>
</resources>

اکنون می توانید متن را بر روی یک شی TextView با ID msg با استفاده از ID منبع به شرح زیر تنظیم کنید

TextView msgTextView = (TextView) findViewById(R.id.msg);
msgTextView.setText(R.string.hello);

مثال:

res / layout / activity_main.xml را با تعریف زیر در نظر بگیرید –

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent" 
   android:layout_height="fill_parent" 
   android:orientation="vertical" >
   
   <TextView android:id="@+id/text"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Hello, I am a TextView" />

   <Button android:id="@+id/button"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Hello, I am a Button" />
      
</LinearLayout>

این کد برنامه این طرح را برای یک Activity بارگذاری می کند ، در روش onCreate () به شرح زیر است:

public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_main);
}

دسترسی به منابع در XML
فایل XML res / values / strings.xml منبع زیر را در نظر بگیرید که شامل یک منبع رنگی و یک منبع رشته ای است:

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <color name="opaque_red">#f00</color>
   <string name="hello">Hello!</string>
</resources>

اکنون می توانید از این منابع در پرونده طرح زیر استفاده کنید تا رنگ متن و رشته متن را به صورت زیر تنظیم کنید:

<?xml version="1.0" encoding="utf-8"?>
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   android:textColor="@color/opaque_red"
   android:text="@string/hello" />

حالا اگر یکبار دیگر فصل قبلی را مرور کنید ، جایی که سلام جهان را توضیح دادم! به عنوان مثال ، و من مطمئن هستم که شما درک بهتری در مورد تمام مفاهیم توضیح داده شده در این فصل خواهید داشت. بنابراین من اکیداً توصیه می کنم فصل قبلی را برای مثال کار بررسی کرده و بررسی کنید که چگونه من از منابع مختلف در سطح بسیار ابتدایی استفاده کرده ام.

جلسه بعد

اجازه دهید برنامه نویسی واقعی را با Android Framework شروع کنیم. قبل از شروع به نوشتن اولین مثال خود با استفاده از Android SDK ، باید مطمئن شوید که محیط توسعه Android خود را به درستی تنظیم کرده اید ، . من همچنین تصور می کنم که شما کمی دانش کار با Android studio دارید.

بنابراین اجازه دهید ما برای نوشتن یک برنامه ساده آندروید که چاپ “Hello World”

برنامه Android ایجاد کنید.

اولین قدم ایجاد یک برنامه ساده آندروید با استفاده از Android studio است. وقتی روی نماد Android studio کلیک می کنید ، همانطور که در زیر نشان داده شده است ، صفحه نمایش داده می شود

برنامه نویسی اندروید

با فراخوانی شروع یک پروژه جدید android studio می توانید توسعه برنامه خود را شروع کنید. در یک چارچوب نصب جدید ، باید از نام برنامه ، اطلاعات بسته و مکان پروژه وارد شود.

برنامه نویسی اندروید

پس از وارد کردن نام برنامه ، به آن فراخوانی می شود که فاکتورهای مورد نظر در برنامه شما را انتخاب کنید ، در اینجا باید حداقل SDK را مشخص کنید ، در آموزش ما ، من به عنوان API23 اعلام کردم: Android 6.0 (Mashmallow) –

برنامه نویسی اندروید

سطح بعدی نصب باید شامل انتخاب فعالیت برای تلفن همراه باشد ، این طرح پیش فرض برنامه ها را مشخص می کند.

برنامه نویسی اندروید

در مرحله نهایی ، ابزار توسعه آزاد برای نوشتن کد برنامه کاربردی خواهد بود.

برنامه نویسی اندروید

آناتومی برنامه اندروید
قبل از اینکه برنامه خود را اجرا کنید ، باید از چند فهرست و پرونده در پروژه Android آگاه باشید –

برنامه نویسی اندروید

JAVA 1
این شامل پرونده های منبع .java برای پروژه شما است. به طور پیش فرض ، این یک فایل منبع MainActivity.java با کلاس فعالیت است که هنگام راه اندازی برنامه شما با استفاده از نماد برنامه اجرا می شود.

res/drawable-hdpi 2
این یک فهرست برای اشیا draw قابل نقاشی است که برای صفحات با چگالی بالا طراحی شده اند.
res/layout 3
این یک فهرست برای پرونده هایی است که رابط کاربری برنامه شما را تعریف می کنند.
res/values 4
این یک فهرست برای سایر پرونده های مختلف XML است که شامل مجموعه ای از منابع ، مانند تعریف رشته ها و رنگ ها است.
5 AndroidManifest.xml
این پرونده آشکار است که خصوصیات اساسی برنامه را توصیف می کند و هر یک از اجزای آن را تعریف می کند.
Build.gradle 6
این یک فایل ایجاد شده خودکار است که شامل compileSdkVersion، buildToolsVersion، applicationId، minSdkVersion، targetSdkVersion، versionCode و versionName

بخش زیر به طور خلاصه پرونده های مهم برنامه را شرح می دهد.

کد فایل Main Activity

کد main activity یک فایل جاوا MainActivity.java است. این پرونده اصلی پرونده است که در نهایت به یک نسخه قابل اجرا Dalvik تبدیل می شود و برنامه شما را اجرا می کند. در زیر کد پیش فرض تولید شده توسط جادوگر برنامه برای Hello World وجود دارد! برنامه

package com.example.helloworld;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {
   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
   }
}

در اینجا ، R.layout.activity_main به پرونده activity_main.xml واقع در پوشه res / layout اشاره دارد. روش onCreate () یکی از روشهایی است که هنگام بارگذاری یک فعالیت مشخص می شود.

فایل Manifest

هر جز component را به عنوان بخشی از برنامه خود توسعه دهید ، باید تمام اجزای آن را در یک manifest.xml که در ریشه دایرکتوری پروژه برنامه قرار دارد ، اعلام کنید. این فایل به عنوان یک رابط بین سیستم عامل Android و برنامه شما کار می کند ، بنابراین اگر جز component خود را در این پرونده اعلام نکنید ، توسط سیستم عامل مورد توجه قرار نمی گیرد. به عنوان مثال ، یک فایل مانیفست پیش فرض مانند فایل زیر خواهد بود.

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

   <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">
         <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
         </intent-filter>
      </activity>
   </application>
</manifest>

در اینجا برچسب <application>…</application> اجزای مربوط به برنامه را در بر می گیرد. ویژگی android:icon به نماد برنامه موجود در res / drawable-hdpi اشاره خواهد کرد. برنامه از تصویری به نام ic_launcher.png که در پوشه های قابل ترسیم قرار دارد استفاده می کند
از برچسب برای تعیین یک فعالیت استفاده می شود و ویژگی android: name نام کلاس کاملاً واجد شرایط زیر کلاس Activity را مشخص می کند و ویژگی های label android: رشته ای را برای استفاده به عنوان برچسب فعالیت مشخص می کند. با استفاده از برچسب می توانید چندین فعالیت را تعیین کنید.
اقدام برای فیلتر intent android.intent.action.MAIN نامگذاری شده است تا نشان دهد این فعالیت به عنوان نقطه ورود به برنامه عمل می کند. این دسته برای فیلتر intent android.intent.category.LAUNCHER نامگذاری شده است تا نشان دهد که برنامه را می توان از نماد راه انداز دستگاه راه اندازی کرد.
string به فایل strings.xml در زیر توضیح داده شده است. از این رو ، @ string / app_name به رشته app_name تعریف شده در فایل strings.xml ، که “HelloWorld” است ، اشاره دارد. به همین ترتیب ، رشته های دیگر در برنامه جمع می شوند.
در زیر لیستی از برچسب ها آورده شده است که برای تعیین م .لفه های مختلف برنامه Android از آنها در پرونده مانیفست خود استفاده خواهید کرد

  • <activity>elements for activities
  • <service> elements for services
  • <receiver> elements for broadcast receivers
  • <provider> elements for content providers

فایل Strings.xml

فایل strings.xml در پوشه res / values قرار دارد و حاوی تمام متنی است که برنامه شما از آن استفاده می کند. به عنوان مثال ، نام دکمه ها ، برچسب ها ، متن پیش فرض و انواع مشابه رشته ها در این پرونده قرار می گیرند. این پرونده مسئول محتوای متنی آنها است. به عنوان مثال ، یک فایل رشته ای پیش فرض مانند فایل زیر خواهد بود.

<resources>
   <string name="app_name">HelloWorld</string>
   <string name="hello_world">Hello world!</string>
   <string name="menu_settings">Settings</string>
   <string name="title_activity_main">MainActivity</string>
</resources>

فایل Layout

activity_main.xml یک فایل طرح بندی موجود در دایرکتوری res / layout است که هنگام ساخت رابط کاربری شما به آن ارجاع می شود. شما برای تغییر چیدمان برنامه خود خیلی مرتباً این فایل را تغییر می دهید. برای “سلام جهان!” برنامه ، این پرونده دارای محتوای زیر است که مربوط به طرح پیش فرض است.

<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" >
   
   <TextView
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_centerHorizontal="true"
      android:layout_centerVertical="true"
      android:padding="@dimen/padding_medium"
      android:text="@string/hello_world"
      tools:context=".MainActivity" />
      
</RelativeLayout>

این نمونه ای از RelativeLayout ساده است که در یک فصل جداگانه مطالعه خواهیم کرد. TextView یک کنترل Android است که برای ساخت رابط کاربری گرافیکی مورد استفاده قرار می گیرد و دارای ویژگی های مختلفی مانند android است: layout_width ، android: layout_height و غیره که برای تنظیم عرض و ارتفاع آن استفاده می شود و غیره.string به فایل رشته های پوشه res / values. از این رو ، @ string / hello_world به رشته سلامی تعریف شده در فایل strings.xml ، که “سلام به جهان!” اشاره دارد.

اجرای برنامه

بیایید سعی کنیم Hello World خود را اجرا کنیم! برنامه ای که ما فقط ایجاد کردیم. من تصور می کنم شما AVD خود را هنگام راه اندازی محیط ایجاد کرده اید. برای اجرای برنامه از Android studio ، یکی از پرونده های فعالیت پروژه خود را باز کنید و از نوار ابزار روی نماد اجرا کلیک کنید. Android studio برنامه را روی AVD شما نصب کرده و شروع به کار می کند و اگر با تنظیمات و برنامه هایتان همه چیز خوب باشد ، زیر پنجره شبیه ساز نمایش داده می شود.

آموزآموزش برنامه نویسی اندرویدش برنامه نویسی اندروید