ورچر

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

آموزش کامل انتخاب عکس از گالری و آپلود آن به سرور در اندروید (به همراه کد های PHP) post image

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

دسته : آموزش
تگ ها : آپلود عکس در اندروید,آپلود عکس به پی اچ پی,ارسال عکس به سرور در اندروید,ارسال عکس به پی اچ پی در اندروید,آپلود فایل در اندروید,آموزش ارسال عکس به سرور در اندروید,آموزش آپلود عکس به سرور در اندروید,آمو
آخرین ویرایش : 1395/7/24

به نام خدا

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

 

کدهای سمت سرور

این کد ها از سایت w3schools بخش آپلود فایل ها گرفته شده است.1.ابتدا در محیط وب سرور خود یک فایل upload.php ایجاد نمایید و کد های زیر را در آن کپی کنید.

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

<?php
$target_dir = "uploads/";
$target_file = $target_dir . basename($_FILES["file"]["name"]);
$uploadOk = 1;
$imageFileType = pathinfo($target_file, PATHINFO_EXTENSION);
$check = getimagesize($_FILES["file"]["tmp_name"]);
if ($check !== false) {
    $uploadOk = 1;
} else {
    $uploadOk = 0;
}

if (file_exists($target_file)) {
    $uploadOk = 0;
}
if ($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg"
    && $imageFileType != "gif"
) {
    $uploadOk = 0;
}
if ($uploadOk == 0) {
    $this->response(['status' => "failed"]);
} else {
    if (move_uploaded_file($_FILES["file"]["tmp_name"], $target_file)) {
        echo json_encode(['status' => "success", "filename" => basename($_FILES["file"]["name"])]); // ساخت جیسون از آرایه و نمایش آن
    } else {
        $this->response(['status' => "failed"]);
    }
}
?>

2. در کنار فایل upload.php یک فولدر با اسم uploads ایجاد کنید تا فایل ها به آنجا آپلود شوند.(در صورتی که محیط کاری شما لینوکس می باشد دسترسی فولدر را به 777 تغییر دهید.)

 

کدهای سمت اندروید

1. ابتدا یک پروژه ای جدید با اکتیویتی MainActivity ایجاد کنید.

2. سپس فایل build.gradle پروژه را باز کرده و در قسمت repositories در سطر پایین jcenter() مقدار mavenCentral() را کپی نمایید. به شکل زیر

allprojects {
    repositories {
        jcenter()
        mavenCentral()
    }
}

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

    compile 'com.loopj.android:android-async-http:1.4.9'
    compile 'com.squareup.picasso:picasso:2.5.2'

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

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> // دسترسی خواندن فایل از مموری برای دریافت عکس از گالری می باشد.
    <uses-permission android:name="android.permission.INTERNET" /> // دسترسی اینترنت می باشد.

5. پس از دسترسی ها نوبت تغییر فایل activity_main.xml می باشد. به شکل زیر تغییر دهید تا یک دکمه برای باز کردن گالری برای آپلود ایجاد شود و یک ایمیج ویو برای لود تصویر در آن پس از آپلود.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="ir.technopedia.myapplication.MainActivity">

    <Button
        android:id="@+id/btn_upload"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="8dp"
        android:text="Upload" />

    <ImageView
        android:id="@+id/img"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true" />

</LinearLayout>

6. حال در کلاس MainActivity.java متغییر های عمومی زیر را تعریف کنید و در تابع onCreate مقدار دهی کنید.به شکل زیر

public class MainActivity extends AppCompatActivity {

    Button btn;// متغییر دکمه آپلود
    ImageView img; // متغییر ایمیج ویو
    final int KeyGallery = 100, ReadExternalRequestCode = 200; // کلید ها برای باز کردن گالری و دریافت دسترسی ها
    String url = "http://192.168.1.104/"; // آدرس وب سرورتون (چون من محلی تست کردم آی پی کامپیوترم هست.)

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

        btn = (Button) findViewById(R.id.btn_upload); // تعریف اشاره گر
        img = (ImageView) findViewById(R.id.img); // تعریف اشاره گر

        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                boolean result = checkPermission(MainActivity.this); // زمانی که دکمه زده شد ابتدا دسترسی ها از کاربر گرفته می شود.(این قسمت به خاطر اندروید M به بعد می باشد.)
                if (result) // در صورتی که دسترسی داده شد این کد اجرا می شود
                    galleryIntent(); // تابع برای باز کردن گالری که فعلا  تعریف نکردیم.
            }
        });

    }
}

7. ابتدا تابع checkPermission(Context context) را به شکل زیر تعریف کنید.(کپی کنید :دی)

توجه : کلید ReadExternalRequestCode برای ارسال نتیجه دسترسی به اکتیویتی اصلی تعریف شده است و در تابع onRequestPermissionsResult برای دریافت دسترسی مربوطه استفاده خواهد شد.

public boolean checkPermission(final Context context) {
        int currentAPIVersion = Build.VERSION.SDK_INT;
        if (currentAPIVersion >= android.os.Build.VERSION_CODES.M) { // ابتدا کنترل می کند تا اندروید بالاتر M باشد
            if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { // اگر دسترسی خواندن مموری را نداشته باشد دستورات داخل شرط اجرا می شود.
                if (ActivityCompat.shouldShowRequestPermissionRationale((Activity) context, Manifest.permission.READ_EXTERNAL_STORAGE)) {
                    AlertDialog.Builder alertBuilder = new AlertDialog.Builder(context);//یک دیالوگ ایجاد می شود.
                    alertBuilder.setCancelable(true);// بصورت قابل کنسل شدنی
                    alertBuilder.setTitle("Permission necessary");// با عنوان نیازمند دسترسی
                    alertBuilder.setMessage("External storage permission is necessary"); // متن دسترسی
                    alertBuilder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { // دکمه مثبت
                        @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
                        public void onClick(DialogInterface dialog, int which) {
                            ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, ReadExternalRequestCode); // نتیجه با کلید ReadExternalRequestCode فرستاده می شود.
                        }
                    });
                    AlertDialog alert = alertBuilder.create(); // دیالوگ را ایجاد میکند.
                    alert.show(); // دیالوگ را نمایش می دهد.
                } else {
                    ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, ReadExternalRequestCode); // نتیجه با کلید ReadExternalRequestCode فرستاده می شود.
                }
                return false;// دسترسی تایید نشده باشد جواب منفی داده می شود.
            } else {
                return true;// دسترسی تایید شده جواب مثبت می شود.
            }
        } else {
            return true;// دسترسی تایید شده جواب مثبت می شود.
        }
    }

8. تابع onRequestPermissionResult() را به شکل زیر override می کنیم.

@Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        switch (requestCode) {
            case ReadExternalRequestCode: // با کلید مربوط به خواندن مموری نتیجه را می خوانیم
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // اگر از درخواست دسترسی جواب مثبت برگشت دستورات شرط اجرا می شود.
                    galleryIntent(); // گالری را باز می کنیم که فعلا تعریف نکردیم.
                } else {
                    Toast.makeText(getBaseContext(), "دسترسی داده نشد!", Toast.LENGTH_LONG).show(); // در صورتی که جواب منفی گرفتیم پیام دسترسی داده نشد را نمایش می دهیم.
                }
                break;
        }
    }

9. تابع galleryIntent() را به شکل زیر ایجاد می کنیم.

توجه : همانند دسترسی ها در هنگام باز کردن یه اکتیویتی برای دریافت نتیجه یک کلید ست می شود که در این قسمت KeyGallery می باشد. این کلید در تابع onActivityResult برای دریافت نتیجه نیز استفاده خواهد شد.

private void galleryIntent() {
        Intent i = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        startActivityForResult(i, KeyGallery); // و با کلید KeyGallery اینتنت را برای دریافت آدرس یک عکس در مموری باز میکنیم.
    }

10. حال تابع onActivityResult را برای دریافت آدرس فایل به شکل زیر override می کنیم.

@Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == Activity.RESULT_OK) { // اگر جوابی فرستاده شد
            if (data == null) { // داده های فرستاده نال باشد کاری نکن
                return;
            } else { // داده های فرستاده مقدار داشته باشد.
                Uri selectedImage = data.getData(); // Uri را بگیر (یوری برای آدرس دهی فایل در سطح سیستم عامل استفاده می شود.)
                if (selectedImage != null) { // اگر یوری خالی نبود عملیات دریافت آدرس فایل را انجا بده یک شی از نوع فایل ایجاد کن و با تابع uploadImage آپلود کن.
                    String[] filePathColumn = {MediaStore.Images.Media.DATA}; 
                    if (!filePathColumn.equals(null)) {
                        Cursor cursor = getContentResolver().query(selectedImage,
                                filePathColumn, null, null, null);
                        cursor.moveToFirst();
                        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
                        String picturePath = cursor.getString(columnIndex); // آدرس فایل انتخاب شده
                        cursor.close();
                        if (!picturePath.equals(null)) {
                            uploadImage(new File(picturePath)); // ایجاد و آپلود شی از نوع فایل 
                        }
                    }
                }
            }
        }
    }

11. تابع uploadImage() را به شکل زیر ایجاد می کنیم.

public void uploadImage(File file) {
        AsyncHttpClient myClient = new AsyncHttpClient();// یک کلاینت اچ تی تی پی ایجاد می کنیم.

        RequestParams params = new RequestParams(); // یک متغییر برای پارامتر های درخواست پست ایجاد می کنیم.
        try {
            params.put("file", file); // فایل را با اندیس file به پارامترها اضافه میکنیم.
        } catch (FileNotFoundException e) {
        }
        myClient.post(url + "android/upload.php", params, new AsyncHttpResponseHandler() { // درخواست را انجام می دهیم.
            @Override
            public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) { // در صورت موفقیت
                try {
                    JSONObject jsonObject = new JSONObject(new String(responseBody)); // آبجکت جیسون را از داده های دریافتی از سرور ایجاد می کنیم.
                    if (jsonObject.getString("status").equals("success")) { // در صورتی که اندیس status مقدار success داشته باشد یعنی داده با موفقیت آپلود شده است.
// در دستورهای زیر آدرس فایل را از جیسون با اندیس filename میگیریم به ایمیج ویو با کمک کتابخانه پیکاسو لود می کنیم.
                        Picasso.with(getBaseContext())
                                .load(url + "android/uploads/" + jsonObject.getString("filename"))
                                .into(img);
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }

            }

            @Override
            public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
// در صورت موفق نبودن آپلود خطا را با تست به کاربر نشان میدهیم.
                Toast.makeText(getBaseContext(), new String(responseBody), Toast.LENGTH_LONG).show();
            }
        });
    }

توجه : آدرس های درخواست ها را با آدرسهای خود مقایسه و هماهنگ کنید.

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

 

حالت پایانی کلاس MainActivity.java به شکل زیر باید باشد.

public class MainActivity extends AppCompatActivity {

    Button btn;
    ImageView img;
    final int KeyGallery = 100, ReadExternalRequestCode = 200;
    String url = "http://192.168.1.104/";

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

        btn = (Button) findViewById(R.id.btn_upload);
        img = (ImageView) findViewById(R.id.img);

        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                boolean result = checkPermission(MainActivity.this);
                if (result)
                    galleryIntent();
            }
        });

    }

    public void uploadImage(File file) {
        AsyncHttpClient myClient = new AsyncHttpClient();

        RequestParams params = new RequestParams();
        try {
            params.put("file", file);
        } catch (FileNotFoundException e) {
        }
        myClient.post(url + "android/upload.php", params, new AsyncHttpResponseHandler() {
            @Override
            public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
                try {
                    JSONObject jsonObject = new JSONObject(new String(responseBody));
                    if (jsonObject.getString("status").equals("success")) {
                        Picasso.with(getBaseContext())
                                .load(url + "android/uploads/" + jsonObject.getString("filename"))
                                .into(img);
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }

            }

            @Override
            public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
                Toast.makeText(getBaseContext(), new String(responseBody), Toast.LENGTH_LONG).show();
            }
        });
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == Activity.RESULT_OK) {
            if (data == null) {
                return;
            } else {
                Uri selectedImage = data.getData();
                if (selectedImage != null) {
                    String[] filePathColumn = {MediaStore.Images.Media.DATA};
                    if (!filePathColumn.equals(null)) {
                        Cursor cursor = getContentResolver().query(selectedImage,
                                filePathColumn, null, null, null);
                        cursor.moveToFirst();
                        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
                        String picturePath = cursor.getString(columnIndex);
                        cursor.close();
                        if (!picturePath.equals(null)) {
                            uploadImage(new File(picturePath));
                        }
                    }
                }
            }
        }
    }

    private void galleryIntent() {
        Intent intent = new Intent();
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(Intent.createChooser(intent, "Select File"), KeyGallery);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        switch (requestCode) {
            case ReadExternalRequestCode:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    galleryIntent();
                } else {
                    Toast.makeText(getBaseContext(), "دسترسی داده نشد!", Toast.LENGTH_LONG).show();
                }
                break;
        }
    }

    public boolean checkPermission(final Context context) {
        int currentAPIVersion = Build.VERSION.SDK_INT;
        if (currentAPIVersion >= android.os.Build.VERSION_CODES.M) {
            if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                if (ActivityCompat.shouldShowRequestPermissionRationale((Activity) context, Manifest.permission.READ_EXTERNAL_STORAGE)) {
                    AlertDialog.Builder alertBuilder = new AlertDialog.Builder(context);
                    alertBuilder.setCancelable(true);
                    alertBuilder.setTitle("Permission necessary");
                    alertBuilder.setMessage("External storage permission is necessary");
                    alertBuilder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                        @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
                        public void onClick(DialogInterface dialog, int which) {
                            ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, ReadExternalRequestCode);
                        }
                    });
                    AlertDialog alert = alertBuilder.create();
                    alert.show();
                } else {
                    ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, ReadExternalRequestCode);
                }
                return false;
            } else {
                return true;
            }
        } else {
            return true;
        }
    }
}