تخفیف ویژه

دوره مجازی اندروید (جلسه 21): کار با AsyncTask و ذخیره فایل در SD card

دسته بندی: اندروید
زمان مطالعه: 1 دقیقه
۱۸ شهریور ۱۳۹۵

به نام خدا، دوستان سلام، در این جلسه می خواهیم پست ها را بعد از دریافت از سرور با استفاده از AsyncTask داخل Sqlite ذخیره کنیم. همچنین تصاویر پست ها را بعد از دریافت در حافظه sd card ذخیره کنیم. مطلب دیگری که در این جلسه آموزش داده ایم، درخواست و چک کردن دسترسی ها در اندروید مارشملو است.

مطالب مطرح شده در این جلسه عبارتند از :

  • معرفی AsyncTask
    • پیاده سازی AsyncTask
    • معرفی doInBackground
    • معرفی preExecute
    • معرفی onPostExecute
    • معرفی onProgressUpdate
  • آشنایی با دریافت و چک کردن permission ها از اندروید مارشملو به بعد
    • چک کردن موجود بودن permission
    • درخواست persmission از کاربر
    • معرفی تابع onRequestPermissionsResult
  • معرفی ProgressDialog
    • معرفی پارامترهای Constructor
    • پیاده سازی عنوان و متن در Progress Dialog
    • معرفی مفهوم indeterminate
    • تغییر استایل Progress Dialog
    • آپدیت کردن مقدار progress
:: توجه

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

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

چه امتیازی به این مقاله می دید؟
نویسنده سعید شاهینی

جلسات دوره

نظرات کاربران

حافظ عباسی

آقای شاهینی در جدیدترین نسخه اندروید رو progressDialog یه خط کشیده یعنی چه؟ لطفا توضیح بدید؟ اگر جایگزینی براش هست لطفا بگید چی هست؟ممنون

Saeed Hoseini

استاد سلام عرض شد.
این ارور یعنی چی؟
10-15 04:18:36.349 660-710/com.example.world.test1 E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
Process: com.example.world.test1, PID: 660
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:325)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:761)
Caused by: java.lang.IllegalStateException: Unrecognized type of request: Request{192.168.1.105/7learn/uploads/pic1.jpg}
at com.squareup.picasso.BitmapHunter$2.load(BitmapHunter.java:66)
at com.squareup.picasso.BitmapHunter.hunt(BitmapHunter.java:206)
at com.squareup.picasso.RequestCreator.get(RequestCreator.java:385)
at com.example.world.test1.DownloadImageTask.doInBackground(DownloadImageTask.java:58)
at com.example.world.test1.DownloadImageTask.doInBackground(DownloadImageTask.java:21)
at android.os.AsyncTask$2.call(AsyncTask.java:305)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
at java.lang.Thread.run(Thread.java:761) 
10-15 04:18:37.043 660-660/com.example.world.test1 E/WindowManager: android.view.WindowLeaked: Activity com.example.world.test1.view.activity.Post1_Activity has leaked window [email protected][ذخیره سازی عکس ها] that was originally added here
at android.view.ViewRootImpl.(ViewRootImpl.java:418)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:331)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93)
at android.app.Dialog.show(Dialog.java:322)
at com.example.world.test1.DownloadImageTask.onPreExecute(DownloadImageTask.java:45)
at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:620)
at android.os.AsyncTask.execute(AsyncTask.java:567)
at com.example.world.test1.view.activity.Post1_Activity.saveImageInSdcard(Post1_Activity.java:85)
at com.example.world.test1.view.activity.Post1_Activity.access$200(Post1_Activity.java:24)
at com.example.world.test1.view.activity.Post1_Activity$1.onRecieved(Post1_Activity.java:48)
at com.example.world.test1.ApiService$3.onResponse(ApiService.java:104)
at com.example.world.test1.ApiService$3.onResponse(ApiService.java:83)
at com.android.volley.toolbox.JsonRequest.deliverResponse(JsonRequest.java:90)
at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:102)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

علی رجبی

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

import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.support.v4.content.ContextCompat;
import android.widget.Toast;

import com.yarolegovich.lovelydialog.LovelyStandardDialog;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;

public class DownloadFile extends AsyncTask<String,Integer,String> {
    ProgressDialog dialog;

    private Context context;
    private String gamepath;
    private String GameName;
    private long sizeData;
    public DownloadFile(Context context, String gamepath,long DataSize,String GameName) {
        this.context = context;
        this.gamepath = gamepath;
        this.sizeData=DataSize;
        this.GameName=GameName;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        showDialog();

    }


    @Override
    protected String doInBackground(String … url) {

       downloadFileFromURL(url);


        return "";
    }



    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        dialog.dismiss();
        Toast.makeText(context, "دانلود شما با موفقیت به اتمام رسید", Toast.LENGTH_SHORT).show();
}


    @Override
    protected void onProgressUpdate(Integer… values) {
        super.onProgressUpdate(values);
        dialog.setProgress(values[0]);
    }

    private void showDialog(){
        dialog =new ProgressDialog(context);
        dialog.setMessage("لطفا تا پایان دانلود،صبر بفرمایید");
        dialog.setTitle("در حال دانلود …");
        dialog.setCancelable(false);
        dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        dialog.show();




    }

    private void downloadFileFromURL(String[] url) {
        try {
            URL myURL;
            myURL = new URL(url[0]);
            URLConnection connection=myURL.openConnection();
            connection.connect();
            int lengthOfFile=connection.getContentLength();
            copyFile(gamepath,myURL,sizeData);

        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(context, "دانلود دیتا با خطا مواجه شد", Toast.LENGTH_SHORT).show();
        }


    }

    private void copyFile(String dataPath,URL url,long sizeOfFile){
        File gameFolder=new File(dataPath);
        try {
            String nameIsoFile= GameName;
            InputStream inputStream=new BufferedInputStream(url.openStream(),1024*10);
            OutputStream outputStream=new FileOutputStream(new File(gameFolder,nameIsoFile));
            byte[] buffer =new byte[1024*10];

            for (int length=0;((length=inputStream.read(buffer))!=-1);length++){
                outputStream.write(buffer,0,length);
                publishProgress((length*100)/((int)sizeOfFile));
            }

            outputStream.flush();
            outputStream.close();
            inputStream.close();


        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(context, "کپی دیتا با خطا مواجه شد", Toast.LENGTH_SHORT).show();
        }


    }
}
سعید شاهینی

سلام، من که با خوندن این کد طولانی چیزی متوجه نمی شم، شما یک breakpoint داخل بدنه متد onProgressUpdate بگذار ببین این متد اصلا فراخونی می شه یا نه.

حامد

حل شد ممنونم
حجم عکس ها بالا بود

حامد

نکته دیگه اینکه
انگار ViewHolder
نیازی نمیبینه که بعد از find کردن Cast انجام بده

 public class CarViewHolder extends RecyclerView.ViewHolder {
        private ImageView Car_Position_image;
        private TextView Car_Position_Title;

        public CarViewHolder(View itemView) {
            super(itemView);
            Car_Position_image = itemView.findViewById(R.id.Car_Position_image);
            Car_Position_Title = itemView.findViewById(R.id.Car_Position_Title);
            context = itemView.getContext();
سعید شاهینی

بله در نسخه های جدید اندروید استودیو دیگه لازم نیست

حامد

سلام
استاد برنامه من بدون ارور بالا میاد
اما RecycleView
خیلی سنگین کار میکنه
تعدا عکس های داخل RecycleView
6-7
//
حدس خود من کلاس DataGenerator
هست که عکس ها باید ادد بشن

public class CarActivity extends AppCompatActivity {

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

        RecyclerView recyclerView=(RecyclerView)findViewById(R.id.recycleView);
        CarAdapter carAdapter=new CarAdapter(this,DataGenerator.getData(this));
        recyclerView.setLayoutManager(new GridLayoutManager(this,2,StaggeredGridLayoutManager.HORIZONTAL,false));
        recyclerView.setAdapter(carAdapter);
    }
///
public class DataGenerator {
    public static List<Car> getData(Context context) {
        List<Car> cars = new ArrayList<>();

        for (int i = 1; i <= 7; i++) {
            Car car = new Car();
            car.setId(i);

            switch (i) {
                case 1:
                    car.setPositonImage(ResourcesCompat.getDrawable(context.getResources()
                            , R.drawable.motor, null));
                    car.setPositionTitle("نمای موتور");
                    break;
                case 2:
                    car.setPositonImage(ResourcesCompat.getDrawable(context.getResources()
                            , R.drawable.dakhel2, null));
                    car.setPositionTitle("نماس فضای داخل ");
                    break;
                case 3:
                    car.setPositonImage(ResourcesCompat.getDrawable(context.getResources()
                            , R.drawable.darb_bironi, null));
                    car.setPositionTitle("درب نمای بیرون");
                    break;
                case 4:
                    car.setPositonImage(ResourcesCompat.getDrawable(context.getResources()
                            , R.drawable.saghf, null));
                    car.setPositionTitle("نمای سقف");
                    break;
                case 5:
                    car.setPositonImage(ResourcesCompat.getDrawable(context.getResources()
                            , R.drawable.jelo_panjare, null));
                    car.setPositionTitle("نمای جلو پنجره");
                    break;
                case 6:
                    car.setPositonImage(ResourcesCompat.getDrawable(context.getResources()
                            , R.drawable.sandogh_aghab_bironi, null));
                    car.setPositionTitle("نمای صندوق عقب");
                    break;

            }
            cars.add(car);

        }
        return cars;


    }
سعید شاهینی

احتمالا حجم عکس هایی که گذاشتید زیاد هست، حجمشون بهتره از 20 کیلوبایت بیشتر نباشه

مهرداد قاسمیان

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

سعید شاهینی

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

مهرداد قاسمیان

در این جلسه با فایل های app_feature کار می کنید. این فایل ها و پروژه رو کی ساختین

سعید شاهینی

داخل ویدیوها نبوده٬ خودم قبل ضبط ساخته بودم

سید فاضل سدره نشین

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

سعید شاهینی

سلام، باشه پاسخ می دم

Intel

آموزش های شما خیلی خوب هستن استاد

theking

باسلام خدمت استاد شاهینی!
استاد میخواستم بدونم چگونه یک عکس رو با مشخص بودن مسیر ذخیره شده بدست بیاریم؟و اون رو داخل imageView لود کنیم؟
با تشکر از شما!

سعید شاهینی

سلام، با استفاده از Picasso می تونید به جای url، ادرس فایل رو بدید.

theking

سلام استاد متوجه شدم !زمانی که اینترنت متصل میشه دیگه نباید از دیتابیس ذخیره شده ،recyclerView تغذیه بشه وباید متدgetPostsّFromDataBase غیرفعال بشه تا متد addPosts کارکنه!

سعید شاهینی

سلام ، از f8 برای خط به خط دیباگ کردن استفاده می کنید؟

پایان زمان پشتیبانی

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

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

نیاز به لاگین

برای ارسال دیدگاه و یا پرسیدن سوال خود در این قسمت، باید در سایت لاگین شوید.