آموزش های این وب سایت به صورت رایگان در دسترس است. اطلاعات بیشتر
مشکل عدم دسترسی خریداران پیشین به برخی آموزش ها برطرف شد
بروز خطا
   [message]
اشتراک در سوال
رای ها
[dataList]

کپی و آپدیت دیتابیس ( آموزش کامل )

Hajhosseini  9 سال پیش  5 سال پیش
+68 0

تا به امروز، من توی برنامه هام دیتابیس رو کپی میکردم و ازش استفاده میکردم، در آپدیت ها دیتابیس قبلی رو پاک میکردم و دیتابیس جدید رو جایگزین میکردم. اما این روش همیشه جواب نمید!
1 : زمانی که حجم دیتابیس بالا باشه
2 : توی بعضی از گوشی ها دیتابیس قبلی پاک نمیشه، در نتیجه آپدیت دیتابیس با مشکل روبه رو میشه
.
روشی که من پیدا کردم استفاده از SQLiteAssetHelper هست که یک Library کامل برای کپی، آپدیت و ... دیتابیس هست.

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

لینک GitHub  : لینک

طریقه استفاده : sqliteassethelper-2.0.1.jar رو در فولدر libs کپی میکنیم

برای استفاده در API پایین تر از 10 ( طبق مستندات ) باید دیتابیس رو به صورت فایل زیپ قرار بدیم مانند : database.sqlite.zip
بعد کلاس زیر رو میسازیم

 public class DataBaseConnection extends SQLiteAssetHelper {

    private static final String DATABASE_NAME    = "database.sqlite.zip";
    private static final int    DATABASE_VERSION = 1;


    public DataBaseConnection(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }
}

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

اینم برای ارتباط با دیتابیس

 private DataBaseConnection db = new DataBaseConnection(this);
+1 0
البته قبلا هم معرفی شده بود لینک :) (9 سال پیش)
+1 0
مرسی اسپریت جان، طریقه آپدیت کردن دیتابیس توی اون تاپیک نبود. ممنون میشم اونو به عنوان پاسخ درج کنید (9 سال پیش)
 برای این سوال 22 پاسخ وجود دارد. مشاهده پاسخ صحیح
پاسخ به سوال 
Hajhosseini  9 سال پیش
+20 0

 پاسخ صحیح

آپدیت کردن هم مانند دیتابیس با حجم بالا تست شد و درست کار میکنه.
از اول کامل توضیح میدم.( به دلیل تغییرات جزئی توی کانستراکتور کلاس )
1 : کلاس sqliteassethelper-2.0.1.jar رو به پروژه اضافه کنید.
2 : یک کلاس به نام 
DataBaseConnection که Extends شده از SQLiteAssetHelper هست رو بسازید و داخلش کدهای زیر رو قرار بدید

 public class DataBaseConnection extends SQLiteAssetHelper {

    public DataBaseConnection(Context context, String name, int version) {
        super(context, name, null, version);

        setForcedUpgrade(version);
    }
    public SQLiteDatabase database() {
        SQLiteDatabase database = null;
        return database;
    }

}

3 : در کلاس ActivityMain یا هر کلاسی که میخواید از دیتابیس استفاده کنید کافیه کد زیر رو استفاده کنید

 DataBaseConnection db = new DataBaseConnection(this, "database", 5);
        final SQLiteDatabase database = db.getReadableDatabase();

        Cursor cursor = database.rawQuery("SELECT * FROM test ", null);
        while (cursor.moveToNext()) {
            try {
                Log.i("LOG", cursor.getString(cursor.getColumnIndex("id")));
            }
            catch (Exception e) {

            }

        }
        cursor.close();
        database.close();

خوب اول بگم این کدی که نوشتم چیکار میکنه، این کد میره از Assets از پوشه databases ، دیتابیسی با نام database که پسوند زیپ داره رو باز میکنه، اگر به نسخه 5 آپدیت نبود اونو آپدیت میکنه و بعد از Table ی به نام test تمام id ها رو لاگ میکنه.
تغییراتی که من دادم اینه که setForcedUpgrade(version); رو به ورژن اضافه کرد، که باعث میشه آپدیت فورس بشه، و version رو به پارامتر های ورودی کانستراکتور اضافه کردم که به راحتی بتونیم ازش استفاده کنید.(در کارهای بزرگتر میتونید به عنوان فیلد تعریفش کنید)
فقط یک نکته وجود داره که اونم اینه که نام دیتابیس و فایل زیپ باید یکی باشن یعنی نام اگر database.sqlite هست، فایل زیپ باید database.zip باشه.
روش های دیگری هم برای آپدیت توی مستندات لینکی که در سوال گذاشتم هست، ولی من چون میخواستم دیتابیس پاک بشه و بعد دوباره کپی بشه این روش برام کارایی داشت، اگر روشی که میخواید این نیست، میتونید به مستندات مراجعه کنید.

0 0
برای دیتا بیس بزرگتر که کپی نمیشه تو گوشی چه کار کنیم دیتا بیس من 10مگ بیشتر نیست ولی کپی نمیشه (8 سال پیش)
+2 0
در صورتی که گوشی جا نداشته باشه کپی نمیشه، ولی در غیر این صورت با این روش تا 40 مگابایت رو هم من کپی کردم. چک کردن فضای گوشی رو هم دوستان قبلا مطرح کردن و میتونید توی انجمن سرچ کنید (8 سال پیش)
0 0
برای دیتا بیس بزرگتر که کپی نمیشه تو گوشی چه کار کنیم دیتا بیس من 10مگ بیشتر نیست ولی کپی نمیشه (8 سال پیش)
0 0
این اصلا چه کار میکونه به کار من میاد (8 سال پیش)
0 0
اگه میدونید کمکم کنید جای دوری نمیره (8 سال پیش)
0 0
دیتابیس در په پوشه ای کپی میشه؟ (8 سال پیش)
0 0
خیلی کمک کردی ممنون (8 سال پیش)
0 0
سلام ممنون یه توضیحی میخواستم! من یه دیتابیسی دارم که نباید به هیچ وجه پاک بشه چون کاربر توش اطلاعاتی رو از توی برنامه ست می کنه بهش! حالا اگه دیتابیس توی این Assets رو تغییر بدیم ساختارشو و یه سری جدول جدید اضافه کنیم توی و نسخه دیتابیسو بالا ببریم توی آپدیت برنامه خودش این جداول و ستون هارو در صورت وجود نداشتن می سازه یا باید دستی ساخت؟ البته از توی برنامه هم ممکنه جداولی ایجاد بشن! آیا این در صورت نبود یه جدول توی دیتابیسی که در Assets هست، اون رو پاک می کنه؟ (7 سال پیش)
0 0
منظورم در کل Upgrade کردن جدوال و ستون های جدید دیتابیس بود (7 سال پیش)
0 0
البته ممکنه بعضی ستون ها هم حذف شن! باید نسخه رو چک کنیم و خودموون دستسی query بزنیم و جدول رو بسازیم یا این خودش این کارو می کنه؟ من فعلا بدون استفاده از این کتابخونه دستی این کارو انجام می دم و بعد انجامش نسخه دیتابیسو بالا می برم. (7 سال پیش)
0 0
این کتابخونه یک دیتابیس میگیره، در صورتی که ورژن تغییر کنه دیتابیس جدید رو جایگزین قبلی میکنه. اینکه شما تیبل های دیگه ای میخواید مشکلی نداره، فقط کافیه توی بعدی اونا باشن، ولی مشکل اصلی اینه که دیتا پاک میشه (تست نکردم ولی به احتمال زیاد پاک میشه). من خیلی وقته از دیتابیس استفاده نمیکنم و تمام دیتا از سرور میاد و در صورت لزوم کش میشه، باید تست کنید ببینید چجوریه. (7 سال پیش)
0 0
مهندس کجا میشه تعیین کرد که کجای sd کپی بشه هیج جیزی نداره ؟ پیش فرض کجا میره میشینه (7 سال پیش)
0 0
اینیم که میگید دیتا پاک میشه ! این اصلا چیز جالبی نیست چون در واقع ورژن اینجا ناکار آمد میشه . همه این کارارو میکنیم که اگر یک دیتابیس پویا داشته باشیم که هرزمان خواستیم بتونیم حداقل حداقل فیلد کم نکنیم بلکه اضافه کنیم .. با این حالتی که شما گفتید فقط تنها مزیتی که داره این دیتابیس اینه که برای داده های بزرگ خوبه درسته !؟ پس دیگه عملا ورژن بی معنی میشه این وسط (7 سال پیش)
0 0
من تست کردم این برنامه دیتابیس رو پاک میکنه و دیتابیس جدید رو جایگزین میکنه (7 سال پیش)
0 0
بدین شکل خیلی بد میشه که ! قک کنین طرف لیست مورد علاقه هاش - خرید هاش و دیگر اطلاعات یوزر و کاربریش که در لوکال ذخیره شده همه میپره و صفر میشه و دیتابیس جدید جایگزین میشه ! (7 سال پیش)
+1 0
سلام. من مدتهاست که از این کتابخانه و کلا دیتابیس آفلاین استفاده نکردم. میتونید سورس پروژه رو باز کنید و مطالعه کنید. شاید خودشون چیزی نوشته باشن، شاید هم ننوشته باشن و نیاز به تغییر در سورس باشه. برای پاک شدن و ... هم، اون زمانی که من این کتابخانه رو گذاشتم، خیلی دیتابیس های آنلاین و آپدیت و ... رایج نبود. الان تمام دیتا در سرور ها ذخیره میشه و کمتر اپلیکیشنی دیتاهاشو روی دیتابیس آفلاین ذخیره میکنه. ولی برای این کار هم شما میتوستید اول دیتاهای دیتابیس رو بخونید، بعد آپدیت رو انجام بدید و بعد از اون دیتا هارو به دیتابیس جدید انتقال بدید. (7 سال پیش)
پاسخ به سوال 
jamal2012  8 سال پیش
+1 0

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

 public class G extends Application {

public static Context context;
public static LayoutInflater inflater;
public static Handler HANDLER = new Handler();
public static Activity currentActivity;

public static SQLiteDatabase database;
public static StructApplication selectedApplication;
public static StructApplicationFav selectedApplicationFav;

public static final String DIR_SDCARD = Environment.getExternalStorageDirectory().getAbsolutePath();
public static String DIR_APP = DIR_SDCARD + "/my_database";


@Override
public void onCreate() {

super.onCreate();
context = getApplicationContext();
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

new File(DIR_APP).mkdirs();

prepareDB();

}


private boolean prepareDB() {

try {
String state = Environment.getExternalStorageState();
InputStream is = context.getAssets().open("norooz.sqlite");

if (state.equals(Environment.MEDIA_MOUNTED))
{

File DB_PATH = new File(DIR_APP + "/norooz.sqlite");

Log.i("DB_PATHDB_PATHDB_PATHDB_PATHDB_PATHDB_PATH", "DB_PATH=" + DB_PATH);

if (DB_PATH.exists()) {

database = SQLiteDatabase.openOrCreateDatabase(DB_PATH, null);
Log.i("databasedatabasedatabasedatabasedatabasedatabase", "database=" + database);

return true;

}
else {

if (copy(new FileOutputStream(DB_PATH), is)) {
database = SQLiteDatabase.openOrCreateDatabase(DB_PATH, null);
return true;
}
else {
return false;
}
}
}
else {
Log.i("hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", "state=" + state);
DIR_APP = getFilesDir().toString();
File dbFile = new File(getFilesDir().toString() + "/" + "/norooz.sqlite");
if (dbFile.exists()) {
database = SQLiteDatabase.openOrCreateDatabase(dbFile, null);
return true;
}
else {
FileOutputStream os = openFileOutput("norooz.sqlite", context.MODE_PRIVATE);
if (copy(os, is)) {
database = SQLiteDatabase.openOrCreateDatabase(dbFile, null);
return true;
}
else {
return false;
}
}
}
}
catch (Exception e) {
e.printStackTrace();
return false;
}
}


private boolean copy(OutputStream os, InputStream is) {
try {
int readed = 0;
byte[] buffer = new byte[8 * 1024];
while ((readed = is.read(buffer)) > 0) {
os.write(buffer, 0, readed);
}
try {
is.close();
}
catch (Exception e) {
e.printStackTrace();
}
try {
os.flush();
}
catch (Exception e) {
e.printStackTrace();
}
try {
os.close();
}
catch (Exception e) {
e.printStackTrace();
}
return true;
}
catch (Exception e) {
e.printStackTrace();
return false;
}
}

}

+5 0
دوست عزیز وقتی از این Library استفاده میکنی نیازی به کپی دیتابیس نیست، خودش کپی میکنه. کدهایی که من نوشتم رو لازم نیست تو کلاس G تعریف کنید. یک کلاس DataBaseConnection به شکل بالا بسازید و هرجا به دیتابیس نیاز داشتید مانند شماره 3 عمل کنید. (8 سال پیش)
0 0
واقعا نیازی نیست یعنی خودلایبرری میاد تشخیص میده که تو یه گوشی کارت حافظه هست یا نه بعد بهترین کارو میکونه (8 سال پیش)
+1 0
دوست من خیلی ممنونم ازت امیدوارم بتونم جبران کنم کوچکترین کاری که میتونم بکونم لایکه !بازم ممنون (8 سال پیش)
پاسخ به سوال 
Vampire  8 سال پیش
+1 0

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

الان یه مشکل کوچیک دارم

تا این دیتابیس کپی بشه روی گوشی کاربر تصویر صفحه سیاه باقی میمونه.

چطوری می تونم یک progress هنگام کپی نمایش بدم ؟

کد های فراخوانی دیتابیس رو داخل کلاس G قرار دادم و در تمام کلاس ها فقط فراخوانی کردم

+2 0
سوال خوبیه، خوب شما میتونید توی اسپلش اسکرین دیتابیستون رو کپی کنید، و زمانی که کپی انجام شد به صفحه اصلی برنامه برید، استفاده از ProgressBar و Thread هم که توضیح داده شده. (8 سال پیش)
0 0
ممنون همین کار رو انجام دادم و کپی و فراخوانی از کلاس splash انجام میشه، داخل thread هم قرار دادم ولی متاسفانه progress bar همچنان هنگ میکنه. بنظرمیاد کد های خود کتابخونه باید تغییر داده بشه (8 سال پیش)
+2 0
خوب شما باید کپی دیتابیس رو روی یک ترد دیگه انجام بدید. (کپی منظور همون کانکت شدنه) (8 سال پیش)
0 0
سلام توو همین انجمن چند جا بحث شده بود که کار با دیتابیس مشکلات زیادی داره.مثلا کارت حافظه نصب هست یا نیست و ... در بعضی از گوشیها هم انگار قضیه فرق میکنه به همین خاطر من سراغ کار با دیتابیس نرفتم. آیا این Library مشکلات رو حل میکنه؟یک سوال دیگه این که گفتید "باید دیتابیس رو به صورت فایل زیپ قرار بدیم" یعنی به صورت دستی این کارو انجام بدیم؟ (8 سال پیش)
+3 0
بله این کتابخونه تمام مشکلات رو حل میکنه، حتی تغییرات توی آپدیت های دیتابیس رو هندل میکنه، سوال دومتون هم، بله باید به صورت دستی دیتابیس رو زیپ کنید و در فولدری که گفتم قرار بدید (8 سال پیش)
0 0
میشه فایل های مثل عکس که داخل drawoble قرار دارند از این روش فشرده و اکسترکت کرد تا حجم برنامه کمتر بشه ؟ (8 سال پیش)
+1 0
از این روش نمیشه، دیتابیس وقتی زیپ میشه حجم قابل توجهی از سایزش کم میشه، ولی عکس اینطور نیست. روش هایی برای زیپ و آنزیپ فایل وجود داره، ولی این کتابخونه فقط دیتابیس رو از زیپ خارج میکنه (8 سال پیش)
پاسخ به سوال 
mtn67  8 سال پیش
+1 0

من نمیتونم استفاده کنم تماما مراحل رو هم درست میرم از این خط خطا میگیره

 final SQLiteDatabase database = db.getReadableDatabase();
+1 0
به db.getWritableDatabase تغییرش بدید (8 سال پیش)
0 0
حاج حسین عزیز من به جای اکتیویتی ، فرگمنت دارم که به This ارور میده و ()getActivity هم گذاشتم باز هم نشد : (DataBaseConnection db = new DataBaseConnection(this, "database", 5). چی بزارم درست شه. و اینکه من لیست ویو دارم که اطلاعات رو از سرور می خونه و می خوام بریزه داخل دیتابیس همینی که شما زحمت کشیدید گفتید و آفلاین نشون بده . چطوری بنویسم کدهاشو؟ اینم جوری که تعریف کردم تو دیتابیس. (8 سال پیش)
0 0
ActivityMain.this رو امتحان کنید حتما جواب میده، اگر توی فرگمنت هستید همون getActivity درسته (8 سال پیش)
0 0
من هم دقیقا طبق آموزش شما کد ها رو نوشتم ولی به این خط final SQLiteDatabase database = db.getReadableDatabase(); خطا میده getReadableDatabase را به getWritableDatabase هم تغییر دام ولی نشد! ممنون میشم راهنمایی کنید! (7 سال پیش)
0 0
از اررورتون اسکرین شات بگیرید بفرستید (7 سال پیش)
پاسخ به سوال 
علی  8 سال پیش
0 0

 "CREATE  TABLE  IF NOT EXISTS news (" +
                "news_id INTEGER PRIMARY KEY  AUTOINCREMENT  NOT NULL  UNIQUE , " +
                "news_title TEXT, " +
                "news_desc TEXT, " +
                "news_date INTEGER " +
                ")");
0 0
راستی این روش رو تمام گوشی ها جواب میده؟ (8 سال پیش)
+1 0
روی همه گوشی ها جواب میده ولی من تابحال با استفاده از این کتابخونه Table نساختم. باز شما امتحان کنید ببینید کار میکنه یا نه (8 سال پیش)
پاسخ به سوال 
mtn67  8 سال پیش
0 0

چرا من نمیتونم از این لایبری استفاده کنم.هر کاری میکنم خطا میده؟؟؟؟؟؟؟؟؟

کدها رو دقیقا کپی میکنم.یه دیتابیس هم ساختم که یک جدول به اسم table داره که داخلش فقط یک سطر به اسم id هست و اونو زیپ کردم داخل assets قرار دادم.

 public class DbActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        DataBaseConnection db = new DataBaseConnection(this, "database", 5);
        final SQLiteDatabase database = db.getReadableDatabase();

        Cursor cursor = database.rawQuery("SELECT * FROM table", null);
        while (cursor.moveToNext()) {
            try {
                Log.i("LOG", cursor.getString(cursor.getColumnIndex("id")));
            }
            catch (Exception e) {

            }

        }
        cursor.close();
        database.close();

    }

خط 20 که خطا گرفته این هست:

 Cursor cursor = database.rawQuery("SELECT * FROM table", null);
0 0
با این لایبری میشه داخل دیتابیس اطلاعات نوشت؟؟؟یا فقط میشه اطلاعات رو خوند؟؟ (8 سال پیش)
+1 0
mtn67 جان فکر کنم میشه نوشت با این دستور : db.getWritableDatabase ولی من نمی دونم اطلاعات json رو چطوری بریزم داخل این دیتابیس که بعد آفلاین هم بشه دید :( (8 سال پیش)
+1 0
table توی دیتابیس شما وجود نداره، باید اسم Table رو بذارید، مثلا tbl_student .هم میشه نوشت، هم اطلاعات رو خوند و کلی قابلیت های دیگه.... علی جان برای وارد کردن اطلاعات فقط کافیه از دستور insert استفاده کنی! (8 سال پیش)
0 0
حاج حسین من دستور insert رو اینجوری وارد کردم در کلاس DataBaseConnection . درسته اینجوری؟ حالا داخل جیسون چی بش بگم؟ (8 سال پیش)
پاسخ به سوال 
علی  8 سال پیش
0 0

 	
public void insert(Long id,String title,String desc,String date){

ContentValues cv=new ContentValues();
cv.put("news_id", id);
cv.put("news_title", title);
cv.put("news_desc", desc);
cv.put("news_date", date);



}
0 0
داخل این کلاس اگه اینترنت وصل نبود از sqlite می خونه و اگر وصل بود از سرور . فقط چطوری بریزه از سرور به sqlite رو نمی دونم چه کدی و کجا استفاده کنم برای insert (8 سال پیش)
پاسخ به سوال 
علی  8 سال پیش
0 0

  public class NewsFragment extends Fragment {

private ArrayAdapter adapter;
public NewsFragment(){}
ProgressDialog mProgressDialog;
ListView lstContent;
ConnectionDetector cd;
DataBaseConnection db;




private ArrayList<StructNews> News = new ArrayList<StructNews>();


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {

View rootView = inflater.inflate(R.layout.fragment_news, container, false);

lstContent = (ListView) rootView.findViewById(R.id.lstContent);

new TestAsync().execute();
cd = new ConnectionDetector(getActivity());
db = new DataBaseConnection(getActivity(), "database", 5);

return rootView;

}

class TestAsync extends AsyncTask<String, Void, String>
{

@Override
protected String doInBackground(String... params) {

if (!cd.isConnectingToInternet()){


final SQLiteDatabase database = db.getReadableDatabase();
Cursor cursor = database.rawQuery("SELECT * FROM news ", null);

StructNews task = new StructNews();

while (cursor.moveToNext()) {
task.id = cursor.getLong(cursor.getColumnIndex("news_id"));
task.title = cursor.getString(cursor.getColumnIndex("news_title"));
task.desc = cursor.getString(cursor.getColumnIndex("news_desc"));
task.date = cursor.getString(cursor.getColumnIndex("news_date"));

News.add(task);
}
cursor.close();




}else{

}

NewsRead();


return null;
}


protected void onPreExecute () {
mProgressDialog = new ProgressDialog(getActivity());
mProgressDialog.setMessage("لطفا صبر کنید...");
mProgressDialog.setIndeterminate(false);
mProgressDialog.show();
super.onPreExecute();
}



protected void onPostExecute(String result){

mProgressDialog.dismiss();
// if (!cd.isConnectingToInternet()){

// Toast.makeText(getActivity().getApplicationContext(), "خطا در برقراری ارتباط.", Toast.LENGTH_SHORT).show();


// }else{


adapter = new AdapterNews(News);
lstContent.setAdapter(adapter);


// }

}


public void onResume() {
adapter.notifyDataSetChanged();

}

}


public void NewsRead() {
String result = Webservice.readUrl("http://192.168.1.1/android/note_server/news.php?action=read", null);

if (result != null) {
try {
News.clear();
JSONArray tasks = new JSONArray(result);
for (int i = 0; i < tasks.length(); i++) {
JSONObject object = tasks.getJSONObject(i);
StructNews task = new StructNews();
task.id = object.getLong("news_id");
task.title = object.getString("news_title");
task.desc = object.getString("news_desc");
task.date = object.getString("news_date") ;
News.add(task);
}


}
پاسخ به سوال 
Hajhosseini  8 سال پیش
+6 0

برای insert توی دیتابیس از کد زیر استفاده کنید

 DataBaseConnection db = new DataBaseConnection(getActivity(), "db_name", App.databaseVersion);
 final SQLiteDatabase database = db.getWritableDatabase();
 database.execSQL(" insert into ... ");
database.close();

برای select کردن هم از کدی که بالا قرار دادم استفاده کنید.

اینکه شما json رو چجوری parse میکنید، ربطی به دیتابیس نداره، شما اطلاعات رو از وب میگیرید، حالا به هر روشی، بعد داخل دیتابیس insert میکنید، سری بعدی اگر آفلاین بود مستقیم از دیتابیس میخونید.

کد هاتون رو یک نگاهی کردم، توی نامگذاری یکم مشکل دارید، هیچ وقت نام متد یا آرایه رو با حرف بزرگ شروع نکنید، و اگر نیازی به Constructor ندارید، ازش استفاده نکنید. کلا تمیز نوشتن خیلی بهتون کمک میکنه، و اگر فقط قسمتی که مشکل دارید رو تو پاسخ درج کنید خیلی بهتره، چون دوستان سریع میبینن و جوابو پیدا میکنن، ولی کد کامل کلاستون رو که میذارید، باید بشینیم از بالا بخونیم که ببینیم چه کارهایی انجام دادید.
********** آپدیت:

 database.execSQL("INSERT INTO student (student_id,student_name_student_age) VALUES ('" + student.id + "','"+student.name+"','" + student.age + "' )"

همین کد ها، اطلاعات student رو توی دیتابیس ذخیره میکنه، اگر شما یک آرایه از student ها دارید، خوب فقط کافیه این خط کد رو توی یک حلقه for قرار بدید و تعداد تکرار رو به اندازه array.size قرار بدید. اون 2 خط بالا رو هم باید قبل از for و 1 خط اخر رو باید بعد از for بنویسید

***** آپدیت 2 *******
دستور گرفتن آخرین آیدی

 select student_id from student where student_id = (select MAX(student_id) from student)
0 0
حاج حسین مرسی بابت ریزبینی ! از حروف بزرگ دیگه استفاده نکردم و تصحیح کردم. بازم ممنون. این عمل insert رو نتونستم دربیارم با این کدی که دادید. :( عمل put نباید انجام بگیره؟ (8 سال پیش)
+1 0
خیر، put برای زمانیه که شما اطلاعات رو توسط json ارسال یا دریافت میکنید، در دیتابیس local نیازی به استفاده از json نیست. (8 سال پیش)
+1 0
بعد شما باید از کلاس News یک object بسازید و اون object رو پاس بدید، نه اینکه مستقیما به کلاس مقدار بدید یا خالیش کنید! News news = new News ...! (8 سال پیش)
0 0
کجا خالیش کردم مگه!؟ حاج حسین همین عمل insert رو میشه خودت بنویسی بگی کدوم قسمت از کلاس News بزارم؟ راستش من مثل شما وارد نیستم هنوز. (8 سال پیش)
0 0
الان این اطلاعات جیسونی که میاد داخل آرایه News چطوری میشه ریخته شه تو دیتابیس Local ? عمل insert چی رو میاد درج میکنه؟ همه اینا سوال شده برام و نمی تونم درست برم جلو :( (8 سال پیش)
+1 0
News.clear اینجا خالیش کرده بودید، شما یک Array از json میگیرید، همون array رو توی دیتابیس insert کنید. پاسخ بالا رو آپدیت میکنم که ببینید چجوری وارد کنید. (8 سال پیش)
0 0
آخ آره یادم نبود clear رو بردارم از کد قبلی. این حلقه for شبیه همین حلقه ی for جیسون هستش دیگه؟ این حلقه for رو تو کدوم متد بزارم که ok باشه؟ (8 سال پیش)
0 0
من گذاشتم تو همین for جیسون ولی این خطا رو میده PRIMARY KEY must be unique و وقتی اینترنت رو قطع می کنم از local که می خونه انگاری از یک id چندبار لود کرده و بقیه news ها نیومده. (8 سال پیش)
0 0
دوست عزیز مشکل شما سمت کار با دیتابیسه، پیشنهاد میکنم ویدیو های استاد تو این فصل رو دوباره ببینید، شما یا باید primery key رو هرسری یدونه جدید اضافه کنید، یا باید auto increment رو فعال کنید و id رو بذارید خود sql ست کنه که من راه دوم رو پیشنهاد میدم. (8 سال پیش)
0 0
من auto increment رو فعال کردم حاج حسین عزیز. حالا وقتی می خوام آفلاین ببینم میره آخرین خبر رو لود می کنه به تعداد خبرهای که ار جیسون گرفتم. (8 سال پیش)
+1 0
این مشکل رو دیگه نمیشه اینجوری جواب داد، شما باید دیباگ کنید، تست کنید، ببینید کجا اشتباه نوشتید، میتونه توی نمایشتون باشه، میتونه از آداپترتون باشه، میتونه از پر کردن آرایتون باشه و کلی چیزای دیگه. حتما دیباگ کنید و مرحله مرحله ببینید چه بلایی سر دیتا میاد (8 سال پیش)
0 0
حاج حسین واقعا ممنون درست شد ، خیلی آذیت کردم شرمنده. فقط یه نکته داره وقتی آنلاین می خونم و میریزه داخل دیتابیس دفعه بعدی که آنلاین می خونم دوباره میریزه داخل دیتابیس. و آفلاین مثلا 4 خبر دارم دوبار 4 خبر میاد خونده میشه. باید دیتابیس هر بار update بشه؟ (8 سال پیش)
+1 0
خواهش میکنم، نه شما باید آیدی آخرین رکورد دیتابیس رو به سرور ارسال کنید، اگر سرور گفت آیتم جدید موجود هست اطلاعات جدید رو براتون بفرسته، اگر نه که اصلا سرور نباید دیتا رو ارسال کنه! (8 سال پیش)
0 0
یعنی شبیه آموزش Market-online database که استاد درس داد برای filter یا sort کردن؟ اگه میشه همینم با نوشتن کد بگید که دیگه اینقدر سرتون رو به درد نیارم :( خجالت (8 سال پیش)
+1 0
این دستورات رو باید توی php ست کنید، برای ارسال آیدی آخرین رکورد هم که اول اخرین رکورد رو که گرفتنشو توی همین پاسخ اضافه میکنم میگیرید و با وب سرویسی که قبلا نوشتید به سرور ارسال میکنید، سرور آیدی رو با دیتابیس خودش چک میکنه اگر آخری بود که هیچی، ولی اگر رکورد جدید داشتیم جدیدارو میفرسته. من php کار نیستم و سمت سرور نمیتونم بیشتر از این راهنماییتون کنم. (8 سال پیش)
پاسخ به سوال 
علی  8 سال پیش
+2 0

این کد سمت php درسته حاج حسین؟ یکی از بچه های PHP گفت به این شکل میشه :گفتم شما هم یه نگاه بندازید ببینید با این کد آیدی که در آخر نوشتید می خوره یا نه.

 $result = mysqli_query($connection,"SELECT * FROM news WHERE (`id` > '{$id}')");
+2 0
علی جان فامیلی من حاج حسینی هست ;) شما همون حسینی بگو بله درسته، تمام رکورد هایی که بیشتر از آیدی ارسالی باشند رو select میکنه (8 سال پیش)
+1 0
واقعا شرمنده حسینی جان :) خیلی ممنون لطف کردی. (8 سال پیش)
0 0
حسینی جان هر کار می کنم کدی که دادی جفت و جور نمیشه . میشه خودت بنویسی دقیقا به چه صورت ok میشه؟ داخل Cursor سلکت کردم ولی مشکله واسم. نمی تونم بفرستمش به php (8 سال پیش)
0 0
الان آیدی رو با دیتابیس خودش چک میکنه اگر آخری بود که هیچی، ولی اگر رکورد جدید داشتیم جدیدارو میفرسته ولی بازم تو لوکال دوباره چند بار کپی میشه! (8 سال پیش)
0 0
حسینی جان آنلاین شدی لطفا جواب این آخری رو بده، نتونستم درستش کنم هر کاری کردم. ممنون (8 سال پیش)
پاسخ به سوال 
علی  8 سال پیش
0 0

 	public void newsRead(){
		    String url = "http://192.168.1.1/android/note_server/news.php";
	        ArrayList<NameValuePair> params = new ArrayList<NameValuePair>();
	        params.add(new BasicNameValuePair("action", "read"));
	        params.add(new BasicNameValuePair("news_id", url));
	      

	        String result = Webservice.readUrl(url, params);
		 if (result != null) {
	           try {
	               
	               JSONArray tasks = new JSONArray(result);
	                 DataBaseConnection  db = new DataBaseConnection(this, "database", 5);
	            final SQLiteDatabase database = db.getWritableDatabase();
	               for (int i = 0; i < tasks.length(); i++) {
	                   JSONObject object = tasks.getJSONObject(i);
	                   StructTask task = new StructTask();
	                   task.id = object.getLong("news_id");
	                   task.title = object.getString("news_title");
	                   task.desc = object.getString("news_desc");
	                   task.date = object.getString("news_date") ;
	                   database.execSQL("INSERT INTO news (news_title,news_desc,news_date) VALUES ('" + task.title + "','" + task.desc + "','" + task.date + "')");
	                   Cursor cursor = database.rawQuery("select news_id from news where news_id = (select MAX(news_id) from news)", null);
	    		       while (cursor.moveToNext()) {
	    		    	   StructTask localTask = new StructTask();
	    		       	localTask.id = cursor.getLong(cursor.getColumnIndex("news_id"));

	    		       }
	    		       cursor.close();
	                   G.tasks.add(task);
	               }
	               
	                database.close();
	           }
	           catch (JSONException e) {
	               e.printStackTrace();
	           }
	       }
0 0
علی جان اینجوری نمیشه نظری داد، شما باید دیباگ کنی، ببینی چه چیزی از وب سرویس میگیری... اگر وب سرویس چیزی برنگردونه که دیگه شما دیتایی نداری که تکراری اد کنه! اول چک کن ببین وب سرویس چه چیزی برمیگردونه، بعد چک کن این دیتا کجا میره و چه کارایی روش انجام میشه، بعد چک کن ببین کجا insert میکنی توی دیتابیس و حتما چک کن ببین دیتا تکراری نباشه... این وسط یه جا مشکل داره که فقط با دیباگه خط به خط میشه مشکلو پیدا کرد (8 سال پیش)
0 0
من وقتی این کد رو اینجا نوشتم یه لحظه اینترنت قطع شده بود فکر کردم دیگه از وب سرویس چیزی نمیفرسته. الان این cersor مقدار همون سلکت شده رو داره ، چطور باید بزارمش بجای این url وقتی int هست و همه ی اون وب سرویس String هستش . این رو چطوری حل کنم؟ (8 سال پیش)
+1 0
باید add params کنی علی جان، من کد آماده ندارم الانم حضور ذهن ندارم که بگم چجوری بود، ولی سرچ کنی خیلی سادست. لینک البته من پیشنهاد میکنم یک object از نوع serializable ارسال کنی... خیلی داینامیک تره، type رو هم generic بگیر... (اگر سخت شد همون معمولی بفرست تا بعدا که وقت داشتی همه اینارو کامل یاد بگیری) (8 سال پیش)
0 0
باید add params کنی علی جان، من کد آماده ندارم الانم حضور ذهن ندارم که بگم چجوری بود، ولی سرچ کنی خیلی سادست. لینک البته من پیشنهاد میکنم یک object از نوع serializable ارسال کنی... خیلی داینامیک تره، type رو هم generic بگیر... (اگر سخت شد همون معمولی بفرست تا بعدا که وقت داشتی همه اینارو کامل یاد بگیری) (8 سال پیش)
پاسخ به سوال 
علی  8 سال پیش
+1 0

دوباره سلام حسینی جان : من یه هفته ای نبودم الان اومدم و فقط سر همین یه تیکه کد مشکل دارم تا کامل حل بشه. این news_id داخلش مقدار آخرین آیدی رو ذخیره می کنه داخل خودش حالا چطوری برسه سمت php . نمی دونم واقعا چکارش کنم. و این موضوع باید حل بشه واسم والا دست بردارش نیستم!

 
String url ="http://192.168.0.0/android/note_server/news.php";

ArrayList
params=newArrayList();

params
.add(newBasicNameValuePair("action","read"));

params
.add(newBasicNameValuePair( url , news_id )); ====>> اینجا

/////////////////////////////////////////////////////////

php

function read(){
    $connection = connectToDatabase();
    $result = mysqli_query($connection,"SELECT * FROM news WHERE ('news_id' > '{$news_id}')");
    $output = array();while($row = mysqli_fetch_array($result)){
        $record = array();
        $record['news_id']= $row['news_id'];
        $record['news_title']= $row['news_title'];
        $record['news_desc']= $row['news_desc']; 
        $record['news_date']= $row['news_date'];
        $output[]= $record;}


    echo json_encode($output);
    mysqli_close($connection);}
+2 0
علی جان نوشتن همه چیز از 0 تا 100 کار درستی نیست، شما داری وب سرویسی رو مینویسی که استاد 2 سال پیش نوشته... گوگل بهترین کتابخونه وب سرویس رو ساخته که کار باهاش واقعا سادست، اگر یک بار از اون استفاده کنی نه مشکلی با این چیزای پیش پا افتاده داری، نه مشکلات دیگه... volley اسم وب سرویسش هست... در مورد مشکل بالا من حضور ذهن ندارم و نمیتونم توی ارسال پارامتر کمکتون کنم، باید با سرچ کردن و یا پرسیدن از دیگر دوستان درستش کنید. (8 سال پیش)
پاسخ به سوال 
محمد رضا  8 سال پیش
0 0

عاقا من از این روش استفاده کردم از  کد زیر مشکل میگیره

 final SQLiteDatabase database = db.getReadableDatabase();

به کد زیر هم تغیر دادم بازم فایده نداشت 

 final SQLiteDatabase database = db.getWritableDatabase()

دیتابیسمم رو هم توی پوشه ی  assets داخل database.zip قرار دادم که اسم فایلم هم database.sqllite هست

 

ممنون میشم کمک کنید .... :(

0 0
احیانا متن خطا رو دوست ندارید قرار بدید؟ (8 سال پیش)
0 0
اول همین اموزش که اقای حاج حسینی دادن ،گفتن که باید اسم دیتا بیس توی برنامه و فولدر assets باید یکی باشه شما یکی رو .zip و اون یکی رو .sqlite گذاشتید..شاید به همین گیر میده! (8 سال پیش)
پاسخ به سوال 
محمد رضا  8 سال پیش
0 0

آقا کسی واقعا مشکل رو نمیدونه ؟؟؟

 

0 0
منم همین مشکلو داشتم، تو خط زیر به جای database گذاشتم database.zip مشکل حل شد شماهم امتحان کن ان شاالله درست شه. ;(DataBaseConnection db = new DataBaseConnection(this, "database.zip",5 (8 سال پیش)
0 0
من database.zip هم گذاشتم حل نشد فقط روی nox کار میکنه هر کاری میکنم روی جنی موشن یا موبایل کرش میکنه چون دیتابیس رو کپی نمیکنه....؟؟؟ (7 سال پیش)
پاسخ به سوال 
tiam  7 سال پیش
0 0

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

private void populatedFromDatabase() {

sections.clear();

try {
DataBaseConnection db = new DataBaseConnection(ActivityMain.this, "Scamper", 5);
final SQLiteDatabase database = db.getReadableDatabase();
Cursor cursor = database.rawQuery("SELECT * FROM Scamper_Section", null);

while (cursor.moveToNext()) {
section = new StructSection();

section.setSectionId(cursor.getInt(cursor.getColumnIndex("section_id")));
section.setSctionEn(cursor.getString(cursor.getColumnIndex("section_en")));
section.setSectionFa(cursor.getString(cursor.getColumnIndex("section_fa")));

Log.i("LOG", "Section ID = " + section.getSectionId());

sections.add(section);

}
cursor.close();
database.close();
} catch (Exception e) {
Toast.makeText(ActivityMain.this, "Error Database", Toast.LENGTH_SHORT).show();

}
}
0 0
اگر از nox جواب میگیرید، احتمال زیاد مشکل از دسترسی های منیفست باشه. اگر نبود موارد مشابه رو تست کنید ولی راهو درست رفتید. (7 سال پیش)
0 0
ممنون حل شد اسم دیتابیس مشکل داشت (7 سال پیش)
0 0
فقط یه سوال با این روش هر بار اجرا یا نصب مجدد دیتابیس پاک میشه و دوباره کپی میشه؟؟ (7 سال پیش)
0 0
اگر version تغییر کنه بله، در غیر این صورت خیر (7 سال پیش)
پاسخ به سوال 
afr_msb  7 سال پیش
0 0

سلام من طبق توضیحات پیش رفتم اینم کدم

         DataBaseConnection db = new DataBaseConnection(SMS_Test2Activity.this, "SmsPost.sqlite", 5);
final SQLiteDatabase database = db.getWritableDatabase();

database.execSQL("INSERT INTO deliver (deliver_sms,tell_sms,message_sms) VALUES (2,'s','s') ");
database.close();
0 0
من برای اینکه عملیات درج در پایگاهم انجام بشه باید چکار کنم ؟ من همه روشی را امتحان کردم با این روش که کلا کرش میکنه دیگه هنگ کردم. تا حالا کسی نمونه ای این پروزه را نداشته که راه حلشو بگه ؟ (7 سال پیش)
0 0
شما خطایی رو که میده رو بزارین تا ببینیم مشکل چیه!دسترسی نوشتن روی مموری کارت رو به برنامتون اضافه کردین؟ (7 سال پیش)
0 0
این دسترسی به مموری کارت به چه صورته ؟ فکر کنم مشکل من همینه (7 سال پیش)
0 0
باید به فایل منیفست پروژتون کد زیر رو اضافه کنین. (7 سال پیش)
0 0
لینک (7 سال پیش)
0 0
ممنون نه تو قسمت منیفست تعریف کزده بودم (7 سال پیش)
0 0
متن خطا رو همینجا توی سوالتون قرار بدید. نیازی نیست در آخر نام دیتابیس sqlite بزنید، نام table که الان deliver هست رو چک کنید. کدی که نوشتید درسته، مشکل از جایی دیگست. اگر از اندروید ورژن 6 استفاده میکنید هم باید runtime permission استفاده کنید. (7 سال پیش)
پاسخ به سوال 
احسان  7 سال پیش
0 0

سلام دوستان 

من با این لایبراری کار کردم و مشکلی هم نداره ولی من توی اندوروید استدیو به دیتابیس چندتا رکورد اضافه کردم و log هم گرفتم و درست بود ولی بعدش فایل دیتا بیس رو برداشتم کپی کردم توی یه برنامه databse manager ولی رکورد هایی که از داخل اندروید استدیو اضافه کرده بودم وجود نداشت ؟!

دلیلش چیه ؟

اینم کد های من ، با این کد های من باید دوتا رکورد به دیتابیسم اصافه بشه که hasan , farid هستن و وقتی هم لاگ میگیرم اضافه میشن  ، ولی وقتی دیتابیس رو با یک نفرم افزار دیتا بیس منیجر باز می کنم خبری از این رکوردهای جدید نیست ؟!

  DataBaseConnection db = new DataBaseConnection(MainActivity.this, "database", 5);
        final SQLiteDatabase database = db.getWritableDatabase();
        database.execSQL("INSERT INTO test (name) VALUES ('hasan')");
        database.execSQL("INSERT INTO test (name) VALUES ('farid')");
        Cursor cursor = database.rawQuery("SELECT * FROM test " , null);
        while(cursor.moveToNext()){

            try{
                Log.i("MINELOG" , cursor.getString(cursor.getColumnIndex("id")));
                Log.i("MINELOG" , cursor.getString(cursor.getColumnIndex("name")));

            }catch (Exception e){

            }
        }

        cursor.close();
        database.close();
+1 0
دلیلش اینه که شما دیتابیس رو توی assets قرار میدی. وقتی برنامه رو ران میکنی دیتابیس توی حافظه داخلی گوشی ذخیره میشه. از این به بعد هر تغییری که شما اعمال کنی روی اون نسخه که توی حافظه قرار داره اعمال میشه. (7 سال پیش)
0 0
خیلی ممنون برای حلش باید چکاری انجام بدم (7 سال پیش)
+1 0
باید اون دیتابیسی که توی حافظه کپی شده رو استفاده کنید. (7 سال پیش)
پاسخ به سوال 
ali  7 سال پیش
0 0

حاج حسین این اروری هست که میده! وقتی توی برنامه روی باتن کلیک می کنم تا اکتیویتی بالا بیاد و متن مورد نظر رو از دیتا بیس بخونه کرش می کنه و این خطا رو میده!

0 0
منظورم این بود که خطا رو اسکرین شات بگیرید نه از صفحتون. الان خطی که خطا گرفته مشخص نیست. برای این کار میتونید لاگ کت رو بزرگتر کنید. اسم دیتابیس رو هم بدون - بذارید. یا حداقل با UnderLine جدا کنید. البته فکر نمیکنم از این باشه ولی امتحانش ضرر نداره (7 سال پیش)
پاسخ به سوال 
ali  7 سال پیش
0 0

اینطوری خوبه؟ اسم دیتابیس رو هم با آندرلاین عوض کردم ولی باز هم خطا گرفت!

0 0
والا از این 3 خط نمیشه فهمید مشکل از کجاست. به نظرم یک بار دیگر مراحل رو چک کنید. امکان داره اسم فایلتون با اسمی که اینجا دادید همخونی نداشته باشه و ... . (7 سال پیش)
پاسخ به سوال 
ali  7 سال پیش
0 0

ببخشید دوباره پیام گذاشتم!

فایل دیتابیس و کتابخانه رو درست گذاشتم؟

0 0
بله درسته. نام دیتابیس با نام فایل زیپ باید یکی باشن. نام دیتابیسی که داخل فایل زیپ هست رو هم database گذاشتید؟ (7 سال پیش)
0 0
نام فایل داخل زیپ اینه: database.sqlite (7 سال پیش)
0 0
آقای مهندس طبق سیستم گیت هاب که گفته فلان خطو بنویس توی dependency مینویسم ولی ارور میده. میشه بگید چطوری باید توی استودیو کاراشو درست کرد (7 سال پیش)
+1 0
@h_uk2009 بعد از اضافه کردن اون توی gradle ابتدا با یک ق ن ش ک ن آی پی رو تغییر بدید بعد اگر اندروید استودیو افلاین هست انلاین کنید(setting->build->buildtools->gradle) و پروژه رو سینک کنید. (7 سال پیش)
پاسخ به سوال 
SeyyedH  7 سال پیش
0 0

من این کارهایی که گفتین انجام دادم اما با اررور زیر مواجه شدم

android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database

که از خط زیر گرفته میشد :

final SQLiteDatabase database = db.getReadableDatabase();

آیا به جز کارهایی گفتین کار دیگه ای باید انجام بشه؟ مثل تعریف کردن کلاس G یا .... چون به چیز دیگه ای اشاره نفرمودین

0 0
فایل دیتابیست روهم بزار داخل asset پوشه database . اگر همه کارها رو کردی باید جواب بدهد (7 سال پیش)
+1 0
من document خودش رو تو سایت github خوندم نوشته بود توی فولدری به نام databases باید باشه، انجام دادم و نتیجه هم داد (7 سال پیش)
0 0
من داخل همین پوشه databases گذاشتم. هم زیپ کردم نشد، و هم بدون زیپ گذاشتم و بازم نشد. هم اسمشو با پسوند گذاشتم (یعنی databa.db) نشد و هم بدون پسوند که بازم نشد. (5 سال پیش)
پاسخ به سوال 
شهریاری 2  5 سال پیش
0 0

دوستان بنده همه کارهایی گفتید رو انجام دادم، اما این ارور رو میده. من داخل همین پوشه databases گذاشتم. هم زیپ کردم نشد، و هم بدون زیپ گذاشتم و بازم نشد. هم اسمشو با پسوند گذاشتم (یعنی databa.db) نشد و هم بدون پسوند که بازم نشد. اینم خطاش. اسم دیتابیس رو گذاشتم tasnim2:

 01-31 21:09:33.877 9928-9928/rasadev.ir.tasnim E/SQLiteLog: (14) cannot open file at line 30052 of [b3bb660af9]
01-31 21:09:33.877 9928-9928/rasadev.ir.tasnim E/SQLiteLog: (14) os_unix.c:30052: (2) open(/data/data/rasadev.ir.tasnim/databases/tasnim2) -
01-31 21:09:33.879 9928-9928/rasadev.ir.tasnim E/SQLiteLog: (14) cannot open file at line 30052 of [b3bb660af9]
01-31 21:09:33.879 9928-9928/rasadev.ir.tasnim E/SQLiteLog: (14) os_unix.c:30052: (2) open(/data/data/rasadev.ir.tasnim/databases/tasnim2)


پاسخگویی و مشاهده پاسخ های این سوال تنها برای اعضای ویژه سایت امکان پذیر است .
چنانچه تمایل دارید به همه بخش ها دسترسی داشته باشید میتوانید از این بخش لایسنس این آموزش را خریداری نمایید .