ذخیره اطلاعات با SharedPreferences در اندروید
به نام خدا. در جلسه گذشته به بررسی دیتابیس در اندروید پرداختیم و با نحوه ذخیره اطلاعات در دیتابیس آشنا شدیم. اما در اندروید روش های دیگری هم برای ذخیره اطلاعات درنظر گرفته شده که در این جلسه به معرفی SharedPreferences می پردازیم. اینکه هرکدام از روش های ذخیره سازی در چه مواردی کاربرد دارد عمدتا به سلیقه توسعه دهنده بستگی دارد اما عموما در کاربردهای متفاوت، با توجه به ویژگی آن، یک گزینه نسبت به دیگری رایج تر بوده و ارجح است. به عنوان مثال برای ذخیره تنظیمات اپلیکیشن (فونت و سایز برنامه، حالت شب/روز، رنگ پس زمینه و…)، ثبت اطلاعات کاربر، نحوه نمایش و چیدمان لیست ها، فعال یا غیرفعال بودن دریافت نوتیفیکشن ها، و به طور کلی داده های با حجم کم، معمولا از SharedPreferences استفاده می شود. SharedPreferences به ما اجازه میدهد تا اطلاعات را با فرمت Key/Value (کلید/مقدار) ذخیره و نگهداری کنیم. این اطلاعات با فرمت xml ذخیره شده و تا زمانی که اپلیکیشن از روی سیستم عامل حذف نشده و یا کاربر به صورت دستی در قسمت تنظیمات برنامه ها، Data ی اپلیکیشن را حذف نکند، باقی می ماند.
متدهای SharedPreferences
برای دستیابی به Preference ها به سه متد دسترسی داریم:
– getPreferences()
– getSharedPreferences()
– getDefaultSharedPreferences()
در این مبحث من از متد getSharedPreferences() استفاده می کنم. قبل از ادامه توضیحات، یک پروژه جدید می سازم که نام آن را Preference گذاشته ام. در ابتدا ساده ترین حالت را در نظر گرفته و تنها یک فیلد ورودی متن (EditText) و یک Button به اکتیویتی activity_main.xml اضافه می کنم تا کاربر نام خود را وارد کرده و ذخیره نماید:
در قدم بعد، این دو Widget را در MainActivity.java تعریف می کنم.
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?> <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="16dp" android:paddingRight="16dp" android:paddingTop="16dp" android:paddingBottom="16dp" tools:context="ir.android_studio.preference.MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <EditText android:id="@+id/edt_name" android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" android:hint="Name" android:inputType="textPersonName" /> <Button android:id="@+id/btn_save" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Save" /> </LinearLayout> </RelativeLayout>
MainActivity.java:
package ir.android_studio.preference; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.Button; import android.widget.EditText; public class MainActivity extends AppCompatActivity { EditText edtName; Button btnSave; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); edtName = (EditText) findViewById(R.id.edt_name); btnSave = (Button) findViewById(R.id.btn_save); } }
حالا از اینترفیس SharedPreferences یک نمونه می سازم. من نام shPref را برای این نمونه در نظر گرفتم:
SharedPreferences shPref;
در ادامه shPref را مساوی متد getSharedPreferences() قرار می دهم:
ملاحظه می کنید این متد دو پارامتر ورودی می گیرد. اولی name و دومی mode. پارامتر نخست مربوط به نام فایلی است که برای ذخیره سازی داده ها استفاده می شود و اختیاری است. من MyPref وارد می کنم (یک متغیر از نوع String با نام MyPref و مقدار MyPrefers ساخته ام. برای موارد بعدی نیز متغیر تعریف می کنم تا از وارد کردن دستی نامها جلوگیری شود که در نهایت منجر به افزایش سرعت و کاهش خطا می شود). پارامتر دوم مربوط به mode (روش) عملیاتی است.
انواع MODE ها
انواع مد ها را بررسی می کنیم:
– MODE_PRIVATE: مد پیش فرض که فایل محتوی داده ها تنها با فراخوانی اپلیکیشن در دسترس خواهد بود.
– MODE_WORLD_READABLE: با این مد سایر اپلیکیشن ها نیز می توانند داده ها را بخوانند که از حیث امنیت ممکن است مشکل ساز شود. (این مد از API 17 به بعد deprecate (منقضی) شده است)
– MODE_WORLD_WRITEABLE: این مد به سایر اپلیکیشن ها اجازه می دهد تا اطلاعات Preference برنامه ما را ویرایش کنند که مانند مورد قبل به لحاظ امنیتی مشکل ایجاد نموده و از API 17 به بعد deprecate شده است.
– MODE_MULTI_PROCESS: این مد تعدیل preferences را چک خواهد کرد حتی اگر Shared Preference قبلا اجرا شده باشد. (این مد از API 23 به بعد deprecate شده است)
– MODE_APPEND: به واسطه این مد، preferences های جدید با preferences های قبلی ترکیب خواهد شد.
ما از MODE_PRIVATE استفاده می کنیم:
shPref = getSharedPreferences("MyPref", Context.MODE_PRIVATE);
خواسته ما از برنامه این است که پس از وارد کردن نام و لمس کلید Save توسط کاربر، نام وارده ذخیره شده و با بستن و اجرای مجدد اپلیکیشن، اطلاعات وارد شده نمایش داده شود. ابتدا متد مربوط به دکمه btnSave را کامل کرده و در ادامه توضیح می دهم.
package ir.android_studio.preference; import android.content.Context; import android.content.SharedPreferences; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends AppCompatActivity { EditText edtName; Button btnSave; SharedPreferences shPref; public static final String MyPref = "MyPrefers"; public static final String Name = "nameKey"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); edtName = (EditText) findViewById(R.id.edt_name); btnSave = (Button) findViewById(R.id.btn_save); shPref = getSharedPreferences(MyPref, Context.MODE_PRIVATE); btnSave.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String n = edtName.getText().toString(); SharedPreferences.Editor sEdit = shPref.edit(); sEdit.putString(Name, n); sEdit.apply(); Toast.makeText(MainActivity.this, "Saved", Toast.LENGTH_LONG).show(); } }); } }
در خط اول متغیری از جنس String با نام n تعریف کردم که با دستور
edtName.getText().toString()
Text ورودی کاربر را از edtName گرفته و در خود ذخیره می کند (توسط getText رشته ورودی دریافت و به وسیله toString به رشته از جنس String تبدیل می شود).
حالا به یک ادیتور نیاز داریم تا به واسطه آن اطلاعات را ذخیره و یا ویرایش کنیم. یک نمونه از SharedPreferences.Editor با نام sEdit ساختم که با shPref.edit() آماده ذخیره و یا ویرایش اطلاعات است.
در مرحله بعد باید محتویات درون n را به Name منتقل کنیم. این کار توسط متد putString انجام می شود:
sEdit.putString(Name, n);
همانطور که از نام متد پیداست، برای ذخیره و یا ویرایش داده های از نوع String بکار می رود. به همین ترتیب برای مقادیر صحیح عددی از متد putInt، مقادیر boolean متد putBoolean، مقادیر شناور متد putFloat و مقادیر long متد putLong استفاده می شود.
در نهایت توسط متد commit() تغییرات اعمال شده ذخیره می شود:
sEdit.commit();
اندروید استودیو به من توصیه می کند به جای commit از متد apply استفاده کنم، بنابراین sEdit.apply() را جایگزین کردم (تفاوتهایی بین این دو وجود دارد که در صورت تمایل با جستجوی عبارت “commit() vs apply()” به جوابهای خوبی خواهید رسید. برای زیبایی کار یک پیغام از نوع Toast به دکمه اضافه کردم تا پس از لمس دکمه عبارت Saved به کاربر نمایش داده شود (در مبحث دیتابیس با Toast آشنا شدیم). تا اینجای کار اگر کد ما مشکلی نداشته باشد اطلاعات وارد شده باید به درستی ذخیره شود. اما هنوز نیاز به یک دستور شرطی داریم تا بعد از خروج کاربر از برنامه و ورود مجدد به آن، چک کند اگر مقادیری در Preference ذخیره شده در محل موردنظر نمایش داده شود. به کد زیر دقت کنید:
if (shPref.contains(Name)) { edtName.setText(shPref.getString(Name, null)); }
این کد می گوید اگر shPref حاوی Name است، توسط متد getString مقدار آنرا گرفته و توسط متد setText روی ویجت edtName نمایش بده.
مشابه متدهای set، متدهای get شامل getString، getInt، getBoolean، getFloat و getLong برای بازیابی داده های ذخیره شده در اختیار ما قرار گرفته است. این متدها نیز دو پارامتر ورودی دارند که اولی کلید مربوط به داده ذخیره شده و پارامتر دوم مقدار پیش فرض است. پیش فرض به این معنی که اگر در کلید مربوطه (به عنوان مثال Name) داده ای ذخیره نشده بود، مقداری که اینجا تعیین کرده ایم به کاربر نمایش داده شود. یک مثال میزنم:
edtName.setText(shPref.getString(Name, "Name not saved!"));
در حالت بالا اگر قبلا در Name چیزی ذخیره نشده باشد، پس از اجرای اپلیکیشن در ویجت edtName عبارت Name not saved! قرار می گیرد. اما چون من قبلا در لایه رابط کاربری مقدار Name را به عنوان hint برای edtName درنظر گرفته ام، از این پارامتر صرف نظر کرده و مقدار null قرار داده ام. البته به جای null رشته خالی یعنی “” هم می توان استفاده کرد:
edtName.setText(shPref.getString(Name, ""));
کد کامل MainActivity:
package ir.android_studio.preference; import android.content.Context; import android.content.SharedPreferences; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends AppCompatActivity { EditText edtName; Button btnSave; SharedPreferences shPref; public static final String MyPref = "MyPrefers"; public static final String Name = "nameKey"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); edtName = (EditText) findViewById(R.id.edt_name); btnSave = (Button) findViewById(R.id.btn_save); shPref = getSharedPreferences(MyPref, Context.MODE_PRIVATE); btnSave.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String n = edtName.getText().toString(); SharedPreferences.Editor sEdit = shPref.edit(); sEdit.putString(Name, n); sEdit.apply(); Toast.makeText(MainActivity.this, "Saved", Toast.LENGTH_LONG).show(); } }); if (shPref.contains(Name)) { edtName.setText(shPref.getString(Name, null)); } } }
پروژه را اجرا می کنم:
یک نام وارد کرده، ذخیره می کنم:
از اپلیکیشن خارج می شوم:
مجدد اجرا می کنم:
برنامه به درستی عمل کرد و نام ذخیره شده در EditText نمایش داده شد. اگر نام فعلی را تغییر داده و مجدد ذخیره کنیم، جایگزین نام قبلی خواهد شد.
دو فیلد ورودی دیگر با عنوان نام خانوادگی و سن نیز به برنامه اضافه می کنم:
package ir.android_studio.preference; import android.content.Context; import android.content.SharedPreferences; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends AppCompatActivity { EditText edtName; EditText edtFamily; EditText edtAge; Button btnSave; SharedPreferences shPref; public static final String MyPref = "MyPrefers"; public static final String Name = "nameKey"; public static final String Family = "familyKey"; public static final String Age = "ageKey"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); edtName = (EditText) findViewById(R.id.edt_name); edtFamily = (EditText) findViewById(R.id.edt_family); edtAge = (EditText) findViewById(R.id.edt_age); btnSave = (Button) findViewById(R.id.btn_save); shPref = getSharedPreferences(MyPref, Context.MODE_PRIVATE); btnSave.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String n = edtName.getText().toString(); String f = edtFamily.getText().toString(); int a = Integer.parseInt(edtAge.getText().toString()); SharedPreferences.Editor sEdit = shPref.edit(); sEdit.putString(Name, n); sEdit.putString(Family, f); sEdit.putInt(Age, a); sEdit.apply(); Toast.makeText(MainActivity.this, "Saved", Toast.LENGTH_LONG).show(); } }); if (shPref.contains(Name)) { edtName.setText(shPref.getString(Name, null)); } if (shPref.contains(Family)) { edtFamily.setText(shPref.getString(Family, null)); } if (shPref.contains(Age)) { edtAge.setText(String.valueOf(shPref.getInt(Age, 0))); } } }
پروژه را مجدد اجرا می کنم:
اطلاعات را وارد کرده و روی دکمه save کلیک می کنم که ذخیره اطلاعات با موفقیت انجام می شود.
مقدار int به تنهایی نمی تواند توسط setText به ویجت ارسال شود. راه حل ساده این است که یک رشته خالی به آن اضافه کنیم:
edtAge.setText(shPref.getInt(Age, 0) + "");
اما من روشی را انتخاب می کنم که اصولی باشد. به اینصورت که توسط String.valueOf() عدد صحیح به String تبدیل شده و سپس به edtAge فرستاده می شود. عدد صفر هم به عنوان مقدار پیش فرض تعیین شده.
برای سادگی و مختصر شدن کد بهتر بود سن را هم از نوع String تعریف کرده و فقط در رابط کاربری، فیلد موردنظر محدود به کاراکترهای عددی می شد. با این حال بهانه ای شد تا از متد putInt و موارد مربوط به تبدیل String به Integer نیز استفاده شود.
اما در Shared Preferences دو متد دیگر نیز در اختیار داریم:
– remove(“KeyName”): توسط این متد می توان دیتا یا دیتاهای مدنظر را حذف کرد.
– clear(): با اجرا شدن این متد کلیه اطلاعات ذخیره شده حذف می گردد.
دو دکمه جدید با نام های “Remove Name and Family” و “Reset” به برنامه اضافه می کنم. تصمیم دارم با کلیک دکمه Remove، نام و نام خانوادگی و با کلیک Reset تمامی اطلاعات حذف شود. متد مربوط به دکمه ها را به صورت زیر تکمیل کردم:
btnRemove.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { SharedPreferences.Editor rEdit = shPref.edit(); rEdit.remove(Name); rEdit.remove(Family); rEdit.apply(); Toast.makeText(MainActivity.this, "Removed!", Toast.LENGTH_LONG).show(); } }); btnClear.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { SharedPreferences.Editor cEdit = shPref.edit(); cEdit.clear(); cEdit.apply(); Toast.makeText(MainActivity.this, "All data cleared!", Toast.LENGTH_LONG).show(); } });
مانند دکمه save ابتدا یک نمونه ساخته و سپس متدهای موردنیاز فراخوانی شده است. توجه داشته باشید در صورتی که متد apply() یا commit() اضافه نشود، تغییرات اعمال نخواهد شد.
پروژه را اجرا می کنم:
اطلاعاتی که قبلا ذخیره شده بود نمایش داده می شود. انتظار دارم با زدن گزینه Remove و سپس بستن و اجرای مجدد برنامه، نام و نام خانوادگی حذف شده باشد:
اطلاعات فیلدهای نام و نام خانوادگی با موفقیت حذف شد. در مرحله بعد برای اطمینان از عملکرد صحیح برنامه، ابتدا نام و نام خانوادگی را مجدد ذخیره کرده و در نهایت روی Reset all کلیک می کنم:
متد clear() نیز به درستی عمل کرده و پس از خروج از برنامه و اجرای مجدد، اطلاعاتی که وارد کرده بودم نمایش داده نمی شود.
دسترسی به فایل Preference
مانند دیتابیس SQLite امکان دسترسی به فایل Preference نیز وجود دارد.
از منوی Tools > Android پنجره Android Device Monitor را باز می کنم. در سمت چپ (Device) نام اپلیکیشن را انتخاب کرده سپس در سمت راست در تب File Manager مسیر زیر را دنبال می کنم:
Data > data > [Application name] > shared_prefs
فایل با همان نامی که تعیین کرده بودم ایجاد شده است. توسط گزینه Pull a file from a device فایل MyPrefers.xml را روی رایانه ذخیره و باز می کنم:
مشاهده می کنید تمامی اطلاعات درون این فایل ذخیره شده است.
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?> <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="16dp" android:paddingRight="16dp" android:paddingTop="16dp" android:paddingBottom="16dp" tools:context="ir.android_studio.preference.MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <EditText android:id="@+id/edt_name" android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" android:hint="Name" android:inputType="textPersonName" /> <EditText android:id="@+id/edt_family" android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" android:hint="Family" android:inputType="textPersonName" /> <EditText android:id="@+id/edt_age" android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" android:hint="Age" android:inputType="number" /> <Button android:id="@+id/btn_save" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Save" /> <Button android:id="@+id/btn_remove" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Remove" /> <Button android:id="@+id/btn_clear" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Reset All" /> </LinearLayout> </RelativeLayout>
MainActivity.java
package ir.android_studio.preference; import android.content.Context; import android.content.SharedPreferences; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends AppCompatActivity { EditText edtName; EditText edtFamily; EditText edtAge; Button btnSave; Button btnRemove; Button btnClear; SharedPreferences shPref; public static final String MyPref = "MyPrefers"; public static final String Name = "nameKey"; public static final String Family = "familyKey"; public static final String Age = "ageKey"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); edtName = (EditText) findViewById(R.id.edt_name); edtFamily = (EditText) findViewById(R.id.edt_family); edtAge = (EditText) findViewById(R.id.edt_age); btnSave = (Button) findViewById(R.id.btn_save); btnRemove = (Button) findViewById(R.id.btn_remove); btnClear = (Button) findViewById(R.id.btn_clear); shPref = getSharedPreferences(MyPref, Context.MODE_PRIVATE); btnSave.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String n = edtName.getText().toString(); String f = edtFamily.getText().toString(); int a = Integer.parseInt(edtAge.getText().toString()); SharedPreferences.Editor sEdit = shPref.edit(); sEdit.putString(Name, n); sEdit.putString(Family, f); sEdit.putInt(Age, a); sEdit.apply(); Toast.makeText(MainActivity.this, "Saved", Toast.LENGTH_LONG).show(); } }); btnRemove.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { SharedPreferences.Editor rEdit = shPref.edit(); rEdit.remove(Name); rEdit.remove(Family); rEdit.apply(); Toast.makeText(MainActivity.this, "Removed!", Toast.LENGTH_LONG).show(); } }); btnClear.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { SharedPreferences.Editor cEdit = shPref.edit(); cEdit.clear(); cEdit.apply(); Toast.makeText(MainActivity.this, "All data cleared!", Toast.LENGTH_LONG).show(); } }); if (shPref.contains(Name)) { edtName.setText(shPref.getString(Name, null)); } if (shPref.contains(Family)) { edtFamily.setText(shPref.getString(Family, null)); } if (shPref.contains(Age)) { edtAge.setText(String.valueOf(shPref.getInt(Age, 0))); } } }
تعداد صفحات : ۲۶
حجم : ۱٫۵ مگابایت
قیمت : رایگان
دانلود رایگان با حجم ۱٫۵ مگابایت لینک کمکی
خسته نباشید واقعا – دستتون هم درد نکنه
سلام و عرض ادب
من مثال بالا رو کار کردم درست بود و ولی اگه بخوایم مقادیر SharedPreferences را در کلاسی دیگر بخوانیم باید چکار کنیم ؟
سلام وقتتون بخیر این برنامه از داده های ورودی تکراری هم جلوگیری میکنه؟ یعنی یه نام و یه نام خانوادگی و یه شماره را نمیشه دوبار سیو کرد؟
خیر خودتون باید مدیریت کنید
سلام ممنون از مطلبتون تقریبا کامله
به جز اینکه چطوری میشه یه آرای لیست رو ذخیره کرد و فراخونی کرد
با سلام
آموزشی که ساختین بسیار واضح و عالی بود که نشون دهنده ی تجربه و میزان کار کردن شما هستش
ممنون از اموزشتون
سلام، ممنون بابت آموزش خوبتون،
چطور از این آموزش برای تنظیمات صفحهی دیگر استفاده کنیم؟
مثلا در Activity تنظیمات، سایز فونت صفحهی mainActivity رو تغییر بدیم؟
سرچ کنید
change app font size using sharedpreferences
سلام شرد پرفرنس رو اولین بار از اینجا اشنا شدم خیلی خوب و کاربردی اموزش دادین خیلی ممنون از صداقت و بزرگ دلیتون
]چطوری میتونم از اطلاعات ذخیره شده در یک اکتیویتی در یک کلاس دیگه استفاده کنم؟
سلام استاد ممنون از سایت خوبتون
من میخوام یه کتاب بسازم که کاربر هر وقت خواست از برنامه خارج بشه بعدا که برنامه رو اجرا میکنه آخرین اکتیویتی که داخلش بوده باز بشه نه اکتیویتی اول
ممنون میشم کمک کنید
سلام
فقط خواستم بگم دمتون گرم که وقت میزارید و اینقدر کامل و تمیز توضیح میدید. امید وارم موفق و سربلند باشید.
ازین که مفید واقع شده خوشحالم
سلام.خیلی واضح و کاربردی ومختصر توضیح دادید.واقعا ممنونم.
سلام
داداش خدا عوضت بده روی یه موردی یه هفته گیر کرده بودم یه نکته ای اشاره کردی اینجا که کلا مسئله رو حل کرد داشتم به فکر عوض کرن اون بخش از نرم افزار می افتادم که این نکته حلش کرد و نرم افزار اونجور که می خواستم شد خدا خیرت بده ممنون
سلام علیکم شما بهترین محتوا ها را در بهترین قالب ها به ما عرضه می کنید و ما از این خدمت بزرگ شما بسیار متشکریم تنها مشکلی که من را ازیت می کند این است که کاش شما در روند تهیه فایل pdf که زممیمه آموزش های شماست کد های نوشته شده را با پسزمینه سیاه قرار ندهید چون کسی مثل من که برای مطالعه این فایل آن را چاپ می کند و فقط خودش استفاده می کند به مشکل نخورد.
با تشکر فراوان از زحمات بی وقفه شما
مثلا شما الان صفحه ی ۵ ی پی دی اف از برنامه ی من رو خوندین بعد خارج میشین . من میخوام ی کاری کنم وقتی دوباره برنامه رو باز کردین بره همون صفحه ی ۵
این مسئله رو دنبالش نبودم تابحال و الان ایده ای به ذهنم نمیرسه
سلام چجوری میتونم با استفاده از این کد وقتی ک برمیگردیم دوباره ب پی دی اف به صفحه ی اخری ک در اون بودیم برگرده؟
متوجه منظورتون نمیشم
سلام
فرض کنید می خوام یک اپ بنویسم که وقتی کاربر login کرد id یا username کاربر رو درون preferences ذخیره کنه و طرف بعداًَ که وارد برنامه میشه login بمونه
حالا سوالی که پیش میاد اینه که اگه یه نفر گوشیش روت باشه میتونه به preferences دسترسی پیدا کنه و username رو عوض کنه و خودش رو به جای یه نفر دیگه جا بزنه و اطلاعات اون رو سرقت کنه یا نه؟
و اگر میتونه چجوری میتونیم از این کار جلوگیری کنیم.
اطلاعی ندارم
سلام دوست عزیز و پسر عم گرامی بارک الله .
کسی ازمن این آموزش رو خواسته بود که برایش بنویسم بعلت مشغله زیاد نمتوانستم لذا یک نگاهی به سایتهای مختلف کردم و ز هیچ کدام خودم خوشم نیامد چون نحوه ارائه مطلب و آموزش با سلیقه ام جور نبودند تا رسیدم به آموزش شما که واقعا بسیار بسیار عالیست این نحوه آموزش قدم به قدم کار ساز است و عالیست .
لذا خواستم تشکر کنم و بگم که به همین نحو و سلک آموزشها را ارائه بدید همه از مبتدی گرفته تا کسایی که کمی بلدند استفاده عالی خواهند کرد به هر حال تشکر و موفق باشید.
شما حرفی در مورد نمایش مقدار ذخیره شده در یک صفحه دیگر نزدین. لطفا یک مثال در این باره بزنید. ممنون
سلام..ممنونم از توضیحات کاملتون.. ببخشید یه سوال داشتم. من میخوام از این نوشته هایی که تو shared preference کاربر ذخیره کرده در اکتیویتی سوم دوباره استفاده کنم و اونجا به نمایش بزاره… بهترین راه برای اینکار چیه؟
خیلی خیلی خیلییییییی ممنون چقدر خوب و واضح این مطلب رو توضیح دادین من خیلی فیلم اموزشی نگاه کردم و سرچ اما توضیح شما فوق العاده کامل و ساده س . انشالله که همیشه سلامت و موفق باشید ما همچنان منتظر تکمیل اموزش شما هستیم
من یه کتاب خریدم ۳۸ تومن ولی یک دهم سایت شما مطلب نداره نوش جااااااااانتان پول این پکیج الان میخرمش
نظر لطف شماست. ان شا الله موفق و پیروز باشید
سلام وقتتون بخیر
واقعا عالی توضیح دادین
ممنونم.
سلام. روش آموزش شما فوق العاده است. فایل های شما خودآموز کامل و تر و تمیزی است که هیچ چیزی را فروگذار نکرده و هیچ ابهامی در آن نیست. با آرزوی تندرستی و موفقیتهای بیشتر برای شما استاد عزیز!
ممنون بزرگوار
سلام..
قبلا توو ایکلیپس با این موضوع کار کرده بودم
اما الان توو استودیو کلی باهاش ور رفتم
نشد که نشد
توو چندتا پیج خارجی هم رفتم اما توو صفحه مقصد نمیتونستم اطلاعات رو واکشی کنم
اما توضیحات شما مفید واقع شد
و موفق شدم..
ممنون، موفق باشید..
سلام،
خیلی ممنون بابت آموزشهاتون. یه سوال داشتم میخواستم بدونم تا اینجا چند درصد از مباحثی که باید یاد میگرفتیم رو یاد گرفتیم؟
خواهش میکنم. حدودا ۳۰ درصد
با سلام و عرض خسته نباشید…
یک انتقاد درخصوص پکی ۱۸۰۰۰ تومانی که امروز دانلود کردم از سایتتون…
اول اینکه آموزش اواش متعلق به آقای بهزاد مرادیه که توی سایت نردبان بود که الان فیلتر شده و تو سایتای دیگه رایگان هست که تو لب تابم داشتم این آموزشو و شما بابتش چول گرفتید و این دور از شان یک سایت معتبر است اگر کر می کنید هستید.
دوم اینکه محتوای اموزش اندرویدتون بسیار بسیار کمه که بالای ۵۰%ش رو اکثر مبتدیا میدونند و اینکه بازه ی زمانی آموزشایی که می زارید خیلی زیاده و فکر کنم تا دو سال دیکه ۲۰ % سایتای خارجی مطلب نزارید.
۱۸۰۰۰ تومان واسه همچین آموزشی دور از انصافه…
امیدوارم رویه رو اصلاح کنید که افراد یشتری جذب شن.
موفق و موید باشید…
با عرض سلام و تشکر از وقتی که گذاشتید بزرگوار
در خصوص پکیج سایت لطفا صفحه مربوطه رو مجدد مطالعه بفرمایید (ان شا الله که قبل از خرید مطالعه فرمودید)
بند اول صفحه پکیج :
«به طور کلی مطالب وب سایت اندروید استودیو به دو قسمت رایگان و غیر رایگان تقسیم می شوند که در انتهای هر مطلب آموزشی فایل PDF برای دانلود در دسترس است. با این حال اگر مایل هستید آموزشهایی که تا این لحظه منتشر شده را یکجا دریافت کنید، نسبت به دانلود و یا دریافت پستی اقدام نمایید.»
در پاراگراف بالا به وضوح اشاره شده که آموزش های موجود در سایت شامل دو دسته رایگان و غیر رایگان هستن. در خصوص جاوا که فرمودید کافیه فصل اول رو (منوی سمت راست سایت) باز کنید. فصل اول آموزشهای جاوا هست که به صورت رایگان قابل دانلوده و داخل متن هم اشاره شده که آموزشها مربوط به وب سایت نردبان هست:
https://android-studio.ir/%d8%a2%d9%85%d9%88%d8%b2%d8%b4-%d8%b2%d8%a8%d8%a7%d9%86-%d8%ac%d8%a7%d9%88%d8%a7
در خصوص کم بودن محتوا هم بله در قسمت معرفی سایت هم عنوان شده که آموزشها به مرور در حال تکمیل هست و ادعایی مبنی بر کامل بودن پکیج نشده و صراحتا عنوان شده برای افرادی هست که قصد دارن آموزشهای سایت (اعم از رایگان و غیر رایگان) رو یکجا و سریع دریافت کنن. مبلغ پکیج بابت ۴ مبحث آموزشی هست که به ترتیب مبالغ ۳، ۴، ۵ و ۶ هزار تومن هستن و مابغی رایگان هست که قبل از خرید می تونستید محتوای سایت رو بررسی کنید و در صورتی که مباحث برای شما سطح پایین بود اقدام به خرید نمیکردید.
این که فرمودید بازه زمانی انتشار آموزشها زیاده بله قبول دارم و تمام سعی بر این هست که این فاصله کاهش پیدا بکنه.
در نهایت مجدد از انتقادتون نسبت به وب سایت تشکر میکنم و خوشحالم که بعد از حدود یک سال و نیم از فعالیت سایت علاوه بر پیامهای ابراز لطف کاربرا بالاخره یک نفر هم انتقاد کرد
سلام
ممنون بابت زحماتتون
کامل ترین آموزش ممکن بود
خسته نباشید واقعا دست مریزاد