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

استاندارد

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

در واقع محتویات فایل، به یک متغیر رشته ای String ، تبدیل می شد و با استفاده از پیغام Toast به کاربر نمایش داده می شود.

در این قسمت هم می خواهیم ، عمل خواندن از فایل را انجام دهیم ولی اینبار می خواهیم که این کار را با استفاده از کلاس FileInputStream انجام دهیم.

با استفاده از کلاس FileInputStream می توانیم عملیات بیشتری را بر روی فایل انجام دهیم.

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

برای این کار باید کد زیر را در قسمت MainActivity.java مورد استفاده قرار دهید.

int length = (int) file.length(); // به دست آوردن طول فایل

byte[] bytes = new byte[length]; //  تعریف متغیر آرایه ای از نوع بایت

FileInputStream in = new FileInputStream(myfile); // نام فایل است myfile
try {
    in.read(bytes); //  bytes خواندن جریان بایت های فایل و نوشتن آن بر روی متغیر
} finally {
    in.close();
}

String contents = new String(bytes); //   به متغیر رشته ای جهت نمایش byte  تبدیل متغیر

البته فرض بر آنست که فایل به صورتی که در بخش های قبلی توضیح داده شده، تعریف شده است.

مثلا به صورت زیر:

String fileName = "1.txt";
String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
String pathDir = baseDir + "/Android/";

File myfile = new File(pathDir + File.separator + fileName);

شرح کد:

فرض می کنیم فایلی به صورتی که در تصویر مشاهده می کنید وجود دارد.

و محتویات آن به این شکل است:

پس مشخصات این فایل بدین صورت است:

      Name: 1.txt

/Directory: /Android

Content: Gsm Developers

دقیقا مثل بخش قبلی ، نام و دایرکتوری فایل را به صورت زیر در کدجاوای پروژه مشخص می کنیم:

String fileName = "1.txt";
String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
String pathDir = baseDir + "/Android/";

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

File myfile = new File(pathDir + File.separator + fileName);

در قسمت اول، pathDir یعنی مسیر دایرکتوری و در قسمت سوم، fileName یعنی همان نام فایل از ورودی های سازنده برای این شی می باشند.

این موارد، در بخش قبلی نیز توضیح داده شد. ولی در این قسمت می خواهیم از کلاس FileInputStream که در واقع جریان ورودی فایل را می خواند استفاده نماییم.

بدین منظور در ابتدا طول فایل را به دست می آوریم:

int length = (int) myfile.length();

سپس یک متغیر آرایه ای به نام bytes از نوع byte معرفی می کنیم و تعداد خانه های آن را برابر با طول فایل در نظر می گیریم.

byte[] bytes = new byte[length];

در مرحله ی بعدی با استفاده از کلاس FileInputStream ، جریان ورودی فایل را به بایت تبدیل کرده و در متغیر آرایه ای bytes می ریزیم.

FileInputStream in = new FileInputStream(myfile);
try {
    in.read(bytes);
} finally {
    in.close();
}

وقتی فایل شما به صورت bytes در بیاید می توانید از آن در قسمت های مختلف کد خود، استفاده نمایید. ولی به دلیل سادگی و پیوسته بودن مطالب در اینجا ما مانند بخش قبل، آن را تبدیل به رشته string می کنیم.

پس در قسمت بعدی، متغیر آرایه ای bytes را به رشته String تبدیل می کنیم تا بتوانیم با استفاده از پیغام Toast آن را به کاربر نمایش دهیم.

String contents = new String(bytes);

در آخر با استفاده از پیغام Toast ، محتویات این رشته به کاربر نمایش داده می شود.

Toast.makeText(getApplicationContext(),contents, Toast.LENGTH_SHORT).show();

نکته:

در بعضی کامپایلرها مثلا Android Studio ، به دلیل آن که فایل ممکن است در حافظه موجود نباشد یا به هر دلیلی قابل خواندن نباشد، دو کد قبلی را در ساختار try-catch می نویسیم.

FileInputStream in = null;
        try {
            in = new FileInputStream(myfile);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        try {
            in.read(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

برای دادن دسترسی ها باید به قسمت AndroidManifest.xml رفته و کد زیر را برای خواندن از حافظه ی خارجی بنویسیم.

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

پروژه را Run می کنیم.

کد کامل MainActivity.java

import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        String fileName = "1.txt";
        String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
        String pathDir = baseDir + "/Android/";

        File myfile = new File(pathDir + File.separator + fileName);

        int length = (int) myfile.length();
        byte[] bytes = new byte[length];

        FileInputStream in = null;
        try {
            in = new FileInputStream(myfile);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        try {
            in.read(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        String contents = new String(bytes);
        Toast.makeText(getApplicationContext(),contents, Toast.LENGTH_SHORT).show();

    }
}

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

استاندارد

در بخش قبلی این موضوع را بررسی کردیم که چگونه می توان، امکان دسترسی خواندن و نوشتن (R/W) در حافظه ی خارجی را با استفاده از کدهای برنامه نویسی، بررسی نمود.

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

من یک پروژه به نام Files-Gsm در اندروید استودیو ایجاد می کنم.

به سراغ کد جاوای برنامه (MainActivity.java) رفته و کد زیر را در متد ()onCreate می نویسم.

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

FileName= 1.txt

Directory = /Android/

سپس با استفاده از پیغام Toast امکان وچود فایل در دایرکتوری مشخص شده، بررسی می شود.

String fileName = "1.txt"; // نام فایل
String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath(); // مسیر پایه حافظه خارجی
String pathDir = baseDir + "/Android/"; // مسیر دایرکتوری

File f = new File(pathDir + File.separator + fileName); // تعریف فایل با استفاده از دو پارامتر نام فایل و مسیر آن
if(f.exists()){
    Toast.makeText(getApplicationContext(),"File Vojud Darad", Toast.LENGTH_SHORT).show(); // پیغامی جهت نشان دادن وجود فایل
        }
else{
    Toast.makeText(getApplicationContext(),"File Vojud Nadarad", Toast.LENGTH_SHORT).show(); //پیغامی جهت عدم وجود فایل 
        }

شرح کد:

فرض می کنیم فایلی به صورتی که در تصویر مشاهده می کنید وجود دارد.

یعنی نام آن:

1.txt

و مسیر آن فایل نیز در مسیر اصلی و پوشه ی Android می باشد.

برای این فایل باید دایرکتوری مسیر زیر را در قسمت کدنویسی جاوا تعریف نماییم:

/Android/

مثلا اگر فایل در پوشه ای به نام Pictures در پوشه ی Telegram باشد (Telegram->Pictures)، مسیر آن به صورت زیر می شود:

/Telegram/Pictures/

پس در مرحله ی اول، نام این فایل را تعریف می کنیم.

String fileName = "1.txt";

سپس مسیر اصلی حافظه ی خارجی (یعنی همان قسمت اصلی که اگر پوشه ی Telegram در آن باشد مسیر به صورت /Telegram/ می شود) را با استفاده از کد زیر به دست می آوریم.

( این مسیر، همان مسیر اصلی می باشد که وقتی فایل منیجر را نصب می کنیم عموما ما را به همین سمت هدایت می کنند)

String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();

در مرحله ی بعدی مسیری که ما می توانیم با استفاده از فایل منیجر خودمان ببینیم را مشخص می کنیم ( مثلا پوشه ی Telegram)

در این جا ما پوشه ی /Android/ را که در حافظه ی خارجی است، تعریف می نماییم.

String pathDir = baseDir + "/Android/";

با کمی دقت متوجه می شوید که این مسیر باعث می شود که مسیری نسبی (/Android/) را نسبت به مسیر پایه (baseDir) که همان حافظه ی خارجی ما است، مشخص نماییم.

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

File f = new File(pathDir + File.separator + fileName);

در قسمت اول، pathDir یعنی مسیر دایرکتوری و در قسمت سوم، fileName یعنی همان نام فایل از ورودی های سازنده برای این شی می باشند.

با استفاده از متد exists که متدی از کلاس File است، و همچنین کار این متد، برای بررسی وجود این فایل می باشد می توان، وجود یا عدم وجود این فایل را در آن دایرکتوری بررسی نمود.

if(f.exists()){
            Toast.makeText(getApplicationContext(),"File Vojud Darad", Toast.LENGTH_SHORT).show();
        }
else{
            Toast.makeText(getApplicationContext(),"File Vojud Nadarad", Toast.LENGTH_SHORT).show();
        }

با استفاده از پیغام Toast ، پیام های تعریف شده در بالا به کاربر نشان داده می شود.

پروژه را Run می کنم.

اگر فایل، طبق تصویر در همان مسیر وجود داشته باشد، مشاهده می کنید که با پیغام “File Vojud Darad” مواجه می شویم.

ولی اگر فایل وجود نداشته باشد، با پیغام “File Vojud Nadarad” مواجه می شویم.

آموزش برنامه نویسی اندروید با اندروید استودیو (بخش پنجاه و پنجم: بررسی امکان دسترسی خواندن و نوشتن در حافظه )

استاندارد

دسترسی خواندن و نوشتن در حافظه موضوع مورد بحث این بخش است.

در این بخش از آموزش برنامه نویسی اندروید، می خواهیم بررسی کنیم که آیا می توانیم فایلی را در حافظه ی خارجی توسط اپلیکیشن بنویسیم؟

به عبارتی آیا اپلیکیشن ما اجازه ی این کار را دارد؟

این بخش، پیش نیاز کار با فایل ها در برنامه نویسی اندروید است.

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

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

که نام انگلیسی آن ها به ترتیب Internal Memory و External Memory می باشد.

کاربر به Internal Memory دسترسی ندارد. بلکه به External Memory دسترسی دارد.

هدف ما در این بخش نیز بررسی دسترسی اپلیکیشن به این حافظه می باشد.

دقت کنید که External Memory را با Sd Card که یعنی کارت حافظه ی Sd ، با قابلیت جداشدن است، اشتباه نگیرید.

برنامه نویسی جاوای این پروژه

به قسمت کد جاوای برنامه یعنی MainActivity.java می رویم.

در ابتدا در متد ()onCreate دو متیر از نوع Boolean معرفی می کنیم.

boolean memoryExternalStorageAvailable = false;
boolean memoryExternalStorageWrite = false;

متغیر اولی، یعنی memoryExternalStorageAvailable بررسی می کند که آیا می توان به حافظه دسترسی پیدا کرد؟ به عبارتی آیا حافظه ی خارجی برای اپلیکیشن حاضر (Available) است؟ (Read)

متغیر دومی، یعنی memoryExternalStorageWrite بررسی می کند که آیا امکان نوشتن در حافظه وجود دارد؟ (Write)

کاری که می خواهیم انجام دهیم اینست که با بررسی با استفاده از کدهایی در قسمت بعدی، در صورت مثبت بودن جواب این سوالات، مقدار True و در صورت منفی بودن جواب این سوالات، مقدار false را به متغیر مربوطه بدهیم.

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

پس یک متغیر رشته ای از یکی از متدهای این کلاس می سازم. و نامش را state به معنی وضعیت می گذارم.

String state = Environment.getExternalStorageState();

مشاهده می کنید که این متغیر یک نوع رشته از متد getExternalStorageState می باشد. که در واقع متد getExternalStorageState وضعیت حافظه ی خارجی را به ما اطلاع می دهد.

در قسمت بعدی با استفاده از یک ساختار کنترلی if-else به بررسی این موضوع می پردازم که آیا حافظه ی خارجی بر روی دستگاه، سوار (mount) شده است یا خیر؟

if (Environment.MEDIA_MOUNTED.equals(state)) {
            memoryExternalStorageAvailable = memoryExternalStorageWrite = true;
        } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
            memoryExternalStorageAvailable = true;
            memoryExternalStorageWrite = false;
        } else {
            memoryExternalStorageAvailable = memoryExternalStorageWrite = false;
        }

در همین ساختار کنترلی است که مقدارهای دو متغیر Boolean ی که در ابتدا تعریف نمودیم، مشخص می شود.

در if دوم، با استفاده از MEDIA_MOUNTED_READ_ONLY به معنی آنست که اگر ، حافظه ی خارجی به صورت Read Only است، فقط متغیر memoryExternalStorageAvailable مقدار True را داشته باشد. که به معنی فقط خواندنی است.

برای این که این موضوع را به اطلاع کاربر برسانیم بهتر است از یک پیغام Toast استفاده کنیم.

پس دو رشته به نام های Readable و Writeable می سازم.

مقدار اولیه ی این دو رشته به ترتیب برابر Not Readable و Not Writable است. ولی اگر از دستور if با موفقیت عبور نمایند، مقدار Can Read Data From External Memory و Can Write Data into External Memory به آن ها داده می شود که این پیغام در آخر با استفاده از یک Toast به کاربر نمایش داده می شود.

String Readable = "Not Readable";
if(memoryExternalStorageAvailable)
    Readable="Can Read Data From External Memory";
String Writeable = "\nNot Writeable";
if(memoryExternalStorageWrite)
     Writeable="\nCan Write Data into External Memory";
Toast.makeText(getApplicationContext(), Readable+Writeable, Toast.LENGTH_SHORT).show();

کد کامل MainActivity.java

import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

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

        boolean memoryExternalStorageAvailable = false;
        boolean memoryExternalStorageWrite = false;
        String state = Environment.getExternalStorageState();

        if (Environment.MEDIA_MOUNTED.equals(state)) {
            memoryExternalStorageAvailable = memoryExternalStorageWrite = true;
        } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
            memoryExternalStorageAvailable = true;
            memoryExternalStorageWrite = false;
        } else {
            memoryExternalStorageAvailable = memoryExternalStorageWrite = false;
        }
        String Readable = "Not Readable";
        if(memoryExternalStorageAvailable)
            Readable="Can Read Data From External Memory";
        String Writeable = "\nNot Writeable";
        if(memoryExternalStorageWrite)
            Writeable="\nCan Write Data into External Memory";
        Toast.makeText(getApplicationContext(), Readable+Writeable, Toast.LENGTH_SHORT).show();

    }
}

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

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

پروژه را Run می کنیم.

آموزش برنامه نویسی اندروید با اندروید استودیو (بخش پنجاه و چهارم: انتقال اپلیکیشن به حافظه SD )

استاندارد

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

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

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

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

به عبارتی اگر پروژه هایی که تا به حال نوشته اید، قابلیت Move to Sd card آن ها، غیرفعال بوده است، به دلیل آن است که این امکان را برای پروژه ی خود به وجود نیاورده بودید.

می توان با دسترسی دادن به این پروژه، طبق چیزی که در زیر گفته شده است، این کار را انجام داد.

ولی ما این آموزش را به صورت پروژه محور انجام داده و با استفاده از Intent ، می خواهیم به سراغ تنظیمات این اپلیکیشن رفته تا این بخش را به صورت مستقیم مشاهده کنیم.

همچنین برای کسانی که می خواهند از درون یک اپلیکیشن به صورت مستقیم، به قسمت تنظیمات آن بروند، آموزش خوبی است.

تعیین دسترسی ها

برای آن که بتوانیم به Sd Card منتقل نماییم و در واقع انتقال این اپلیکیشن به حافظه Sd ، باید دسترسی های آن را پیکربندی نماییم.

به سراغ manifests->AndoirdManifest.xml می رویم. سپس کد زیر را در تگ manifest> اضافه می کنیم.

android:installLocation="auto"

دقت نمایید که همین کار برای فعال شدن Move to Sd Card کافی ست.

طراحی Layout اپلیکیشن

ما در اینجا سعی می کنیم این آموزش را به صورتی پروژه محور انجام داده تا با ارائه مثالی عملی این کار را انجام دهیم.

من یک پروژه در اندروید استودیو ایجاد می کنم و نامش را Sd-Card-Gsm می گذارم.

به سراغ Layout اپلیکیشن (activity_main.xml) می رویم و یک دکمه Button ایجاد می کنیم.

<Button
        android:text="Move to Sd Card"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"
        android:id="@+id/button"
        android:onClick="AppManager"/>

دقت نمایید که به دکمه Button بالا یک خاصیت onClick اضافه نمودیم که مقدار آن AppManager می گذاریم تا متد آن را بعدا در قسمت جاوای برنامه بنویسیم.

android:onClick="AppManager"/>

کاری که این دکمه Button انجام می دهد اینست که با کلیک بر روی آن، برنامه به اکتیویتی تنظیمات این اپلیکیشن رفته تا عملیات Move to Sd Card را برای آن انجام دهیم.

MainActivity.java

به سراغ برنامه نویسی این پروژه (MainActivity.java) می رویم تا کدهای جاوای آن را بنویسیم.

در این قسمت ، در کلاسMainActivity ، یک متد به نام AppManager ایجاد می کنیم.

کاری که این متد برای ما انجام می دهد اینست که با استفاده از این Intent ، وقتی به روی دکمه Button کلیک نماییم، به قسمت تنظیمات (Settings) این اپلیکیشن می رویم.

این متد به شکل زیر است:

public void AppManager(View view) {
        String packageName = "com.gsm_developers.sd_card_gsm";

        try {
            Intent intent = new  Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
            intent.setData(Uri.parse("package:" + packageName));
            startActivity(intent);
        }
        catch (ActivityNotFoundException e) {
            Intent intent = new  Intent(android.provider.Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS);
            startActivity(intent);
        }
    }

 

کدهای بالا را شرح می دهیم:

در قسمت try این متد، یک Intent به نام intent می سازیم که به application details این برنامه دسترسی داشته و وارد آن شویم.

Intent intent = new  Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);

ولی در ابتدای این متد، یک متغیر به نام packageName از نوع رشته می سازیم که مقدار آن را برابر نام پکیج این پروژه قرار می دهیم.

String packageName = "com.gsm_developers.sd_card_gsm";

باید نام پکیج این اپلیکیشن وقتی به Sd Card منتقل شود، را به این Intent تخصیص دهیم.

intent.setData(Uri.parse("package:" + packageName));

در قسمت بعدی باید این Intent را با استفاده از کد startActivity شروع (Start) نماییم.

startActivity(intent);

کد کامل MainActivity

package com.gsm_developers.sd_card_gsm;

import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends AppCompatActivity {

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

    public void AppManager(View view) {
        String packageName = "com.gsm_developers.sd_card_gsm";

        try {
            Intent intent = new  Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
            intent.setData(Uri.parse("package:" + packageName));
            startActivity(intent);
        }
        catch (ActivityNotFoundException e) {
            Intent intent = new  Intent(android.provider.Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS);
            startActivity(intent);
        }
    }
}

یادتان باشد که دسترسی این اپلیکیشن را نیز تغییر دهید.

یعنی به سراغ manifests->AndoirdManifest.xml رفته و سپس کد زیر را در تگ manifest> اضافه می کنیم.

android:installLocation="auto"

 کد کامل manifest این اپلیکیشن را در زیر مشاهده می کنید.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.gsm_developers.sd_card_gsm"
    android:installLocation="auto">

    <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>

کار به اتمام رسیده است، پروژه را Run می کنیم.

با زدن دکمه ی Move To Sd Card به بخش Settings این اپلیکیشن می رویم.

مشاهده می کنید که این قسمت برای این اپلیکیشن فعال شده است.

آموزش برنامه نویسی اندروید با اندروید استودیو (بخش پنجاه و سوم: Context Menu )

استاندارد

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

ContextMenu در سیستم عامل ویندوز و … هم وجود دارد. بدین صورت که وقتی بر روی فایلی کلیک می کنید، می توانید با کلیک راست بر روی آن کارهایی که می توانید بر روی فایل انجام دهید را ببینید.

ولی در اندروید این کار با استفاده از نگه داشتن طولانی مدت (Hold) بر روی فایل انجام می شود.

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

در این بخش، با استفاده از Context Menu می خواهیم ، عملیاتی را بر روی لیست ویو (ListView) ها انجام دهیم.

مثلا این که بتوانیم نام مخاطبینی را در لیست ویو قرار بدهیم، و عملیاتی نظیر تماس و ارسال پیام را برای این لیست ویو انجام دهیم.

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

من یک پروژه در اندروید استودیو ایجاد می کنم و نامش را ContextMenu-Gsm می گذارم.

ابتدا به سراغ Layout برنامه می رویم و یک لیست ویو را به لایه اپلیکیشن، اضافه می کنیم.

کد لیست ویو من :

<ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/listview"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_marginTop="23dp" />

 

خط “android:id=”@+id/listview را به صورت دستی اضافه نمودم.

در قسمت بعدی باید در MainActivity.java ، کدهای جاوای لازم را برای لیست ویو بنویسیم.

همچنین Context Menu نیز در این بخش توضیح داده می شود.

در متد ()onCreate لیست ویو را تعریف کرده و با استفاده از آداپتر ، مقدارهایی که با استفاده از آرایه رشته ای به آن دادیم، را به لیست ویو اضافه می کنیم.

ListView listView;
String myContacts[]={"Iliya","kurosh","Arya","Mehrdad","Behnam"};
listView=(ListView)findViewById(R.id.listview);
ArrayAdapter<String> adapter=new  ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,myContacts);
listView.setAdapter(adapter);

تمام مراحل بالا در بخش سی ام توضیح داده شد. ولی یک کد در انتهای متد ()onCreate به این بخش اضافه شده است.

این کد عبارت است از :

registerForContextMenu(listView);

در این کد که listView ما به صورت آرگومان ورودی آن ، قرار گرفته است، ما لیست ویویی که نوشتیم را برای عملیات Context Menu که بعدا تعریف میکنیم آماده می کنیم.

در خارج از متد ()onCreate یک متد به نام onCreateContextMenu تعریف کرده و در آن کدهایی می نویسیم تا در هنگامی که Context Menu باز شود، مقادیری که می خواهیم به ما نشان داده شود.

public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo)
    {
        super.onCreateContextMenu(menu, v, menuInfo);
        menu.setHeaderTitle("انتخاب عملیات");
        menu.add(0, v.getId(), 0, "تماس");
        menu.add(0, v.getId(), 0, "پیامک");
    }

مثلا در کد بالا ، Context Menu ما، عنوانی به نام “انتخاب عملیات” دارد.

همچنین دو عملیات “تماس” و “پیامک” را نیز برای Context Menu در این بخش تعریف می کنیم.

در مرحله بعد متدی از نوع boolean به نام onContextItemSelected تعریف می کنیم تا وقتی بر روی عملیات مربوطه مثلا تماس کلیک کردیم، کارهایی که می خواهیم را برای ما انجام دهید.

public boolean onContextItemSelected(MenuItem item){
        if(item.getTitle()=="تماس"){
            Toast.makeText(getApplicationContext(),"You Can Define Calling Code Later",Toast.LENGTH_LONG).show();
        }
        else if(item.getTitle()=="پیامک"){
            Toast.makeText(getApplicationContext(),"You Can Define Sending Sms Code Later",Toast.LENGTH_LONG).show();
        }else{
            return false;
        }
        return true;
    }

همان طور که در کد بالا مشاهده می کنید، با استفاده از دستورات کنترلی If ، عملیاتی که می خواهیم را نوشته ایم.

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

if(item.getTitle()=="تماس")

کد MainActivity.java

package com.gsm_developers.contextmenu_gsm;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

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

        ListView listView;
        String myContacts[]={"Iliya","kurosh","Arya","Mehrdad","Behnam"};
        listView=(ListView)findViewById(R.id.listview);
        ArrayAdapter<String> adapter=new  ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,myContacts);
        listView.setAdapter(adapter);

        registerForContextMenu(listView);
    }

    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo)
    {
        super.onCreateContextMenu(menu, v, menuInfo);
        menu.setHeaderTitle("انتخاب عملیات");
        menu.add(0, v.getId(), 0, "تماس");
        menu.add(0, v.getId(), 0, "پیامک");
    }
    public boolean onContextItemSelected(MenuItem item){
        if(item.getTitle()=="تماس"){
            Toast.makeText(getApplicationContext(),"You Can Define Calling Code Later",Toast.LENGTH_LONG).show();
        }
        else if(item.getTitle()=="پیامک"){
            Toast.makeText(getApplicationContext(),"You Can Define Sending Sms Code Later",Toast.LENGTH_LONG).show();
        }else{
            return false;
        }
        return true;
    }

}

پروژه را Run می کنیم.

مشاهده می کنید که لیست ویو ما همان مواردی که به  آن اضافه نمودیم را نشان می دهد.

با نگه داشتن طولانی بر روی یکی از این آیتم ها ، Context Menu به ما نشان داده می شود.

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

آموزش برنامه نویسی اندروید (بخش چهل و سوم: کلمات پیشنهادی با استفاده از AutoCompleteTextView )

استاندارد

بارها برای شما پیش آمده که در پلتفرم اندرویدی خودتان، با نوشتن حرف اول یک کلمه، پیشنهادهایی به شما داده شود. این کار باعث جستجوی سریع تر کلمه مورد نظر و در نتیجه راحتی کار کاربر می شود.

AutoCompleteTextView در اندروید وظیفه این کار را بر عهده دارد. AutoCompleteTextView یک نوع از جستجوی پیشرفته را ارائه می دهد که این نوع از جستجوی کلمات را انجام می دهد.

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

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

در ابتدا برای شروع، من یک پروژه به نام AutoComplete-Gsm ایجاد می کنم. سپس به قسمت لایه اپلیکیشن یعنی فایل activity_main.xml می روم. از قسمت Paletteها یک AutoCompleteTextView را به لایه اپلیکیشن Drag & Drop می کنم (می کشم) .

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

کد Xml ابزار AutoCompleteTextView :

<AutoCompleteTextView
        android:text="AutoCompleteTextView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="180dp"
        android:id="@+id/autoCompleteTextView"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_marginLeft="20dp"
        android:layout_marginStart="64dp" />

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

حال به قسمت کد جاوای برنامه یعنی فایل MainActivity.java رفته تا کدهای جاوای اپلیکیشن را بنویسیم.

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

String[] MyDict={"Farvardin","Ordibehesht","Khordad","Tir","Mordad","Shahrivar",
                "Mehr","Aban","Azar","Dey","Bahman","Esfand",
                 "Ali","Fantasy","Emsal","Os","Kif","Saham"};

حال برای لیست کردن این رشته ها باید از یک ArrayAdapter استفاده کنیم. چون در قسمتی که می خواهیم از آرایه ی رشته ای که تعریف کرده ایم استفاده نماییم، باید اطلاعات به صورت لیست شده باشند. ArrayAdapter وظیفه لیست کردن این اطلاعات ( در اینجا ماه های سال و … که به صورت String تعریف کردیم) را برعهده دارد.

ArrayAdapter<String> adapter = new ArrayAdapter<String> (this,android.R.layout.select_dialog_item,MyDict);

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

AutoCompleteTextView actv=  (AutoCompleteTextView)findViewById(R.id.autoCompleteTextView);

لازم به ذکر است که کلاس لایبراری زیر باید در کدجاوای برنامه Import شود تا AutoCompleteTextView بتواند در قسمت جاوای برنامه شناخته شده و مورد استفاده قرار گیرد:

import android.widget.AutoCompleteTextView;

همان طور که در کد بالا نوشتیم، نام AutoCompleteTextView در کد جاوای برنامه actv است. در قسمت بعدی از متد setThreshold برای actv استفاده می کنیم:

 

کد این قسمت:

actv.setThreshold(1);

اگر به کد بالا با دقت نگاه کنید، متوجه می شوید که در آرگومان ورودی برای متد setThreshold عدد 1 گذاشته شده است. این عدد برای اینست که به AutoCompleteTextView بگوییم تنها با اولین حرفی که وارد کرده ایم شروع به جستجو کن.  در صورتی که عدد 2 را وارد کنیم، پس از وارد کردن دو حرف اول کلمه، برنامه شروع به جستجوی کلمات پیشنهادی می کند.

حال باید رشته ای که به صورت لیست شده با استفاده از ArrayAdapter انجام دادیم را به actv یعنی همان AutoCompleteTextView معرفی کنیم:

actv.setAdapter(adapter);

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

actv.setTextColor(Color.RED);

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

دقت کنید که تنها با وارد کردن حرف a ، کلمات پیشنهادی که با حرف a شروع می شوند به شما نمایش داده می شود.

پس برای آن که لیستی کامل تر داشته باشید بهتر است از یک فایل دیکشنری پر از کلمات پیشنهادی استفاده کنید. فایل دیکشنری را در برنامه به صورت لیست شده با استفاده از ArrayAdapet به AutoComplete ی که تعریف کرده اید بدهید.