# Native Code > برنامه نویسی موبایل > Android Studio >  راهکار تحریم گوگل چیه؟ چطوری کاربران اپلیکیشن بدون وی‌پی‌ان از Firebase تو ایران استفاده کنن؟

## aesshoferi

سلام،

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

----------


## hharddy

استفاده ازسیستم های ایرانی  و خارجی دیگه یا خرید سرور و پیاده سازی کردن سرویس ها

----------


## hamed9090

> استفاده ازسیستم های ایرانی  و خارجی دیگه یا خرید سرور و پیاده سازی کردن سرویس ها


میشه بیشتر توضیح بدید؟؟
اگه ایرانی هست نام ببرید..
و با خرید سرور چگونه؟؟؟
ممنون

----------


## farhad_shiri_ex

> استفاده ازسیستم های ایرانی و خارجی دیگه یا خرید سرور و پیاده سازی کردن سرویس ها


دوست عزیز چرا مبهم جواب میدی اگر اطلاعاتی دارید واضح تر بیان کنید...! وگرنه این مطلب که می فرمایید که همه میدونیم!!
بعد سیستم ایرانی برای جایگزین فایر بیس چی؟؟
خرید سرور منظورتون مثلا کدوم شرکت هست که سرویس های مثل فابریک را ارائه بده البته شرکتهایی که خدمات ابری و پوش و ... اینهارو ارائه میدن اکثرشون را می شناسم اونها منظورم نیست؟؟




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


دوست عزیز فایر بیس سرویس های زیادی داره ولی معمولا ما تو ایران یا حداقل شرکتهایی که برنامه های معتبری دارند برای جبران بخشی از این سرویسها از سرویس های www.fabric.io استفاه میکنیم فوق العاده ست البته اینم فیلتره ولی روش هایی داره که ازش استفاده کنید برای اینکه دانش بهتری نسبت به این سرویس پیدا کنید بهتره از سورسهای نرم افزار آی گپ را مطالعه کنید.

----------


## Nevercom

سرویس FCM که برای Push Notification استفاده میشه که برای ایران مشکلی نداره و کاربران دلخل ایران هم Push رو دریافت می‌کنن، سرویس‌های زیادی هم بر اساس همین FCM ساخته شدن که همه خوب می‌شناسیدشون.

جایگزین سرویس Realtime Database، پروژه‌ی RethinkDB هست که اوپن سورس هست.
برای قابلیت های Analytics میشه از Matomo (قبلن اسمش Piwik بود) استفاده کرد که اوپن سورس هست.

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

----------


## aesshoferi

فرهاد جان ممنونم. آی‌گپ را سالها پیش بنده نوشتم و با fabric و امثالهم آشنایی کافی دارم ولی برای پروژه جدیدم که هدف مشتریان ایرانی و خارجی هست بهترین سرویس firebase هست که به صورت integrated all-in-one سرویس‌هاشو ارائه کرده. فعلا برای جلب نظر سرمایه‌گذار مجبورم تمرکزمو روی مارکت ایران بذارم ولی از فایربیس نمیتونم استفاده کنم ولی در آینده اولویت با مارکت خاورمیانه، اروپا و آمریکاست در این شرایط میتونم فایریس رو جایگزین کنم ولی این کار باعث data loss و دردسر فراوانی میشه. این دو تا کار به ذهنم رسیده، ابتدا از سرویس‌های دیگه استفاده کنم تا محصولمو تو بازار ارزیابی کنم یا از همین ابتدا به قول دوستمون یه سرور بگیرم سرویس‌های اوپن سورسو روش run کنم. شما نظر دیگه‌ای داری کمکم کنه

----------


## aesshoferi

دوستان با کلی تحقیق و فکر تصمیم گرفتم از سرویس‌های زیر استفاده کنم.
Parse Config (back4app.com)Fabric CrashlyticsFabric AnalyticsPusher

همچنین تصمیم گرفتم بک‌اند رو با PHP+Laravel بنویسم؛ بنابراین، authentication رو با Laravel Passport پیاده میکنم.

حالا به مزایا و معایب این تصمیم با رنگ سبز و قرمز می‌پردازم.

از integrated all-in-one بودن فایربیس محروم شدمبرای پیاده‌سازی authentication باید خودم دست به کار شمهزینه بیشتری می‌پردازمدستم تو کار بازه

اینم بهتون بگم خرید سرور+پیاده‌سازی پروژه‌های اوپن سورس هزینه کمی داره ولی به مراتب هزینه نگهداری، توسعه و پیاده‌سازی بیشتری داره. همچنین پروژه‌های اوپن سورس امکانات کافی ندارن.

اگر هم دوستان پرسیدن چرا پی‌اچ‌پی و nodejs نه، این انتخاب بستگی زیادی به پروژه داره. در پروژه‌ای که ارتباط realtime با کلاینت داره باید بتونه پاسخگوی نیاز همزمان ۵۰۰٫۰۰۰ کاربر و بیش از ۱۰ میلیون request در روز باشه. البته بگم بدون شک انتخابم nodejs بود تا اینکه بنچمارک PHP7 رو دیدم. در چنین شرایطی پرفورمنس حرف اولو میزنه، بنابراین باید سمت سرور هم به‌خوبی تنظیم بشه که load balancing به خوبی درصد قابل توجهی به پرفورمنس پروژه کمک می‌کنه. میزبانی پروژه هم به digitalocean و کانفیگشو به laravel forge سپردم

----------


## farhad_shiri_ex

> آی‌گپ را سالها پیش بنده نوشتم


آب در کوزه ما تشنه لب ...

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

    compile 'com.mikepenz:fastadapter-commons:3.0.3@aar'
    compile 'com.mikepenz:fastadapter-extensions:3.0.3@aar'
    compile 'com.mikepenz:materialize:1.0.3@aar'
compile 'com.android.support:multidex:1.0.1'
    compile 'com.readystatesoftware.systembartint:systembartin  t:1.0.4'

منظور از تکه کد زیر چی ؟

configurations.all {
    resolutionStrategy.eachDependency { DependencyResolveDetails details ->
        def requested = details.requested
        if (requested.group == 'com.android.support') {
            if (!requested.name.startsWith("multidex")) {
                details.useVersion '26.0.2'
            }
        }
    }
}

در باره کتابخانه realm هم اگر توضیحاتی بدید که ممنون خواهم شد!


   private static final long xFFFFFF = 0xFFFFFF;
    private static final int xFF = 0xFF;

    private static final DateFormat SDF_MED = SimpleDateFormat.getDateTimeInstance( //
            SimpleDateFormat.MEDIUM, //
            SimpleDateFormat.MEDIUM);
    private static final SUID[] INSTANCES = new SUID[xFF + 1];

    static { // initiate 0-255 instances, to avoid duplication
        for (int i = 0; i <= xFF; i++) {
            SUID instance = new SUID();
            instance.instanceId = i;
            INSTANCES[i] = instance;
        }
    }

    private final AtomicLong INC = new AtomicLong();
    private int instanceId = 0; // instanceId for different applications

    public static SUID id(int instanceId) {
        if (instanceId < 0 || instanceId > xFF) return null;
        return INSTANCES[instanceId];
    }

    public static SUID id() {
        return INSTANCES[0];
    }

    public static String toString(long id) {
        String hex = Long.toHexString(id);
        return hex.subSequence(0, 8) //
                + "-" + hex.substring(8, 14) //
                + "-" + hex.substring(14);
    }

    public static String toStringLong(long id) {
        long time = (System.currentTimeMillis() >> 42 << 42) + (id >> 22);
        long inc = (id >> 8) & xFFFFFF;
        long instanceId = id & xFF;

        return id + " (DEC)"//
                + "\n" + toString(id) + "  (HEX)" //
                + "\ntime=" + SDF_MED.format(new Date(time)) + ", instanceId=" + instanceId + ", inc=" + inc;
    }

    public static void main(String[] args) {
        System.out.println("\n--- get id");
        System.out.println(toStringLong(id().get()));
        System.out.println(toStringLong(id().get()));

        System.out.println("\n--- get id by app id");
        System.out.println(toStringLong(id(13).get()));
        System.out.println(toStringLong(id(13).get()));

        System.out.println("\n--- duplication test ...");
        long id = 0, ts = System.currentTimeMillis();
        Set<Long> set = new HashSet<Long>();
        for (int i = 0; i < 1000 * 1000; i++) {
            id = id(i & 1).get();
            if (!set.add(id)) System.out.println("!!!!!! duplication found:" + toStringLong(id));
        }
        System.out.println("--- duplication test passed, cost " + (System.currentTimeMillis() - ts) + "ms");
    }

    public long get() {
        return ((System.currentTimeMillis() >> 10) << 32) // timestamp
                + ((INC.incrementAndGet() & xFFFFFF) << 8) // auto incremental
                + instanceId // instance id
                ;
    }

این تکه کد بالا دقیقا چه کاری میکنه؟؟
مورد استفاده اش چی بوده ؟؟

----------


## aesshoferi

> آقا بی زحمت یه توضیح راجع به این کتابخانه ها بده که چرا تو آی گپ استفاده شده و مورد استفاده هاش کجاست تو برنامه !


کار اون دیپندنسی‌ها که معلومه! fastadapter یه لایبراری که adapter رو با کلی امکانات پیاده کرده. البته الآن توصیه میکنم flexibleadapter استفاده کنید. materialize هم باز دوست خوبمون mike penz نوشته که یه سری کارای متریالی رو با ساپورت از نسخه‌های قدیمی انجام میده مثل رنگ کردن status bar و اینا... multidex که واسه خود اندرویده و وقتی تعداد متدهای استفاده شده در کل اپ که شامل دیپندنسی‌ها هم میشه به ۶۴ هزار برسه باید اپ رو به چندین dex تقسیم کنه. این دیپندنسی نیازه این کاره. دیپندنسی آخرو نمیشناسم حقیقتا دنبالشم نرفتم خودت صفحه گیت‌هابشو بخون.




> منظور از تکه کد زیر چی ؟


بچه‌هایی که بعد من اومدن تغییرات دادن ولی بنظر میاد این تکه کد اضافیه و بخاطر حذف warning های بیلد هست که میتونستن بیخیالشون بشن چون اررور نیستن ولی از این حرفم مطمئن نیستم.




> در باره کتابخانه realm هم اگر توضیحاتی بدید که ممنون خواهم شد!


برو مستنداتشو بخون  :لبخند گشاده!:  الان ولی توصیه میکنم یا از room استفاده کنی یا sql خام بزنی که به مراتب سرعت بیشتری داره. البته باید هوشمندانه انتخاب کنی و بستگی به برنامه و استیج پروژت و محدودیت‌هات داره.




> این تکه کد بالا دقیقا چه کاری میکنه؟؟
> مورد استفاده اش چی بوده ؟؟


بنظر میاد کلاس util شون باشه و حدس میزنم آیدی unique میخواستن چون اگه حتی System.currentTimeMillis یا nano حتی داخل for بزنی در بعضی شرایط خروجی یکسانی دارن اینقدر for سریع اجرا میشه بنابراین نیاز به متدی داشتن که مطمئن بشن آیدی منحصربه‌فرد دارن

----------


## Nevercom

configurations.all {
    resolutionStrategy.eachDependency { DependencyResolveDetails details ->
        def requested = details.requested
        if (requested.group == 'com.android.support') {
            if (!requested.name.startsWith("multidex")) {
                details.useVersion '26.0.2'
            }
        }
    }
}


بنظر میاد که این تکه کد به gradle میگه که برای تمام کتابخانه‌های com.android.support از یک نسخه‌ی خاص استفاده کن، بجز کتابخانه‌ی multidex.

چون مهمه که همه‌ی این کتابخانه از یک نسخه استفاده کنن، من شماره نسخه رو بصورت متغیر در میارم و از اون متغیر بجای شماره نسخه برای هر dependency استفاده می‌کنم، این تکه کد کار رو راحت تر کرده و خودش اینکار رو می‌کنه.

----------


## Nevercom

> اگر هم دوستان پرسیدن چرا پی‌اچ‌پی و nodejs نه، این انتخاب بستگی زیادی به پروژه داره. در پروژه‌ای که ارتباط realtime با کلاینت داره باید بتونه پاسخگوی نیاز همزمان ۵۰۰٫۰۰۰ کاربر و بیش از ۱۰ میلیون request در روز باشه. البته بگم بدون شک انتخابم nodejs بود تا اینکه بنچمارک PHP7 رو دیدم. در چنین شرایطی پرفورمنس حرف اولو میزنه، بنابراین باید سمت سرور هم به‌خوبی تنظیم بشه که load balancing به خوبی درصد قابل توجهی به پرفورمنس پروژه کمک می‌کنه. میزبانی پروژه هم به digitalocean و کانفیگشو به laravel forge سپردم


از وقتی اینو خوندم ذهنم مشغولش شده. من سالهاست با PHP کار می‌کنم و اخیراً بنا به نیاز، از NodeJS هم استفاده می‌کنم.
واقعیت این هست که مدل Non-blocking I/O که NodeJS داره، اون رو برای کاربردهای خاصی خیلی متمایز می‌کنه و مدل معمول Request/Response که مشخصه PHP هست و تقریباً تمام توابعش Blocking هستند، اون رو برای کارکردهای دیگری مناسب می‌کنه.

آمار ۱۰ میلیون درخواست اینجا نگران کننده نیست، حدود ۱۱۵ درخواست در ثانیه، که در پروژه ای و روی یک سرور معمولی، نیمی از این مقدار رو به راحتی پاسخ میدم. بخصوص که لود بالانسر رو هم قراره درنظر داشته باشید.

اما ماهیت Real-time و تعداد کاربر همزمانی که ذکر کردید، کمی نگران کننده هست، موضوع بهینگی مفسر PHP نیست، موضوع اینه که همونطور که می‌دونید در PHP به ازای هر درخواست باید تمام آبجکت ها ساخته بشن و در انتهای درخواست هم از بین میرن.
به این، بوت‌استرپ کردن یک فریم‌وورک بزرگ مثل لاراول رو هم اضافه کنید.

ضمن اینکه در PHP بر خلاف NodeJS، از همون ابتدا با مدل event-driven رو برو نمیشید و اگر قراره مثلاً با Socket بصورت Real-time خدمات داده بشه، باید الگوی متفاوت از الگوی مرسوم PHP استفاده بشه.
مدتی هست دنبال فرصت و بهانه ای هستم تا Swoole رو تست کنم، اما فرصتش ایجاد نشده. این پست شما همون دغدغه ها رو به یادم آورد و خواستم حداقل اینها رو توصیه کنم تا بررسی کنید، شاید تونست به پرفرمنس بهتر پروژه‌تون کمک کنه.

در یک بنچمارک برای NodeJS عدد ۱۲،۰۰۰ درخواست در ثانیه ذکر شده که برای PHP حدود ۳۰۰۰ بود، اما با اکستنشن Swoole در PHP به عدد خیره‌کننده ۷۲،۰۰۰ رسیده بود (البته ناگفته نماند که Swoole بر مبنای Worker هست، و چندین Worker رو برای پرفرمنس بهتر ران می‌کنه که در Node باید با ابزاری مثل PM2 همون کار رو انجام داد، که مطمئن نیستم انجام شده بود). همون بنچمارک رو پیدا نکردم که لینک بدم.

حتی اگر قراره از Laravel استفاده کنید، شاید استفاده PPM (یا PHP Process Manager) راهکار معقولی برای افزایش پرفرمنس باشه.

به هرعنوان، قطعاً در بررسی‌هایی که کردید خیلی از این موارد رو درنظر داشتید، اما خیلی خوشحال میشم اگر درآینده تجربه‌ی واقعیتون در این پروژه رو از بعد پرفرمنس به اشتراک بزارید.

پیروز باشید

----------


## aesshoferi

تو چند روزی که از ارسال اون پست میگذره، بک‌اند ساده‌ای با node php go elixir نوشتم و پرفورمنس هرکدوم رو بدون بار فریم‌ورک و ماژول خاصی مقایسه کردم و فهمیدم elixir بهترین گزینه برای داشتن به سیستم scalable و realtime هست البته باتوجه به استیج محصول بک‌اند رو موقتا با php می‌نویسم. دوست خوبم خوشحال میشم باهات درتماس باشم اگه مایل هستی شمارتو خصوصی بذار  :چشمک:

----------


## farhad_shiri_ex

> کار اون دیپندنسی‌ها که معلومه! fastadapter یه لایبراری که adapter رو با کلی امکانات پیاده کرده. البته الآن توصیه میکنم flexibleadapter استفاده کنید. materialize هم باز دوست خوبمون mike penz نوشته که یه سری کارای متریالی رو با ساپورت از نسخه‌های قدیمی انجام میده مثل رنگ کردن status bar و اینا... multidex که واسه خود اندرویده و وقتی تعداد متدهای استفاده شده در کل اپ که شامل دیپندنسی‌ها هم میشه به ۶۴ هزار برسه باید اپ رو به چندین dex تقسیم کنه. این دیپندنسی نیازه این کاره. دیپندنسی آخرو نمیشناسم حقیقتا دنبالشم نرفتم خودت صفحه گیت‌هابشو بخون.
> 
> 
> بچه‌هایی که بعد من اومدن تغییرات دادن ولی بنظر میاد این تکه کد اضافیه و بخاطر حذف warning های بیلد هست که میتونستن بیخیالشون بشن چون اررور نیستن ولی از این حرفم مطمئن نیستم.
> 
> 
> برو مستنداتشو بخون  الان ولی توصیه میکنم یا از room استفاده کنی یا sql خام بزنی که به مراتب سرعت بیشتری داره. البته باید هوشمندانه انتخاب کنی و بستگی به برنامه و استیج پروژت و محدودیت‌هات داره.
> 
> 
> بنظر میاد کلاس util شون باشه و حدس میزنم آیدی unique میخواستن چون اگه حتی System.currentTimeMillis یا nano حتی داخل for بزنی در بعضی شرایط خروجی یکسانی دارن اینقدر for سریع اجرا میشه بنابراین نیاز به متدی داشتن که مطمئن بشن آیدی منحصربه‌فرد دارن





> کار اون دیپندنسی‌ها که معلومه! fastadapter یه لایبراری که adapter رو با کلی امکانات پیاده کرده. البته الآن توصیه میکنم flexibleadapter استفاده کنید. materialize هم باز دوست خوبمون mike penz نوشته که یه سری کارای متریالی رو با ساپورت از نسخه‌های قدیمی انجام میده مثل رنگ کردن status bar و اینا... multidex که واسه خود اندرویده و وقتی تعداد متدهای استفاده شده در کل اپ که شامل دیپندنسی‌ها هم میشه به ۶۴ هزار برسه باید اپ رو به چندین dex تقسیم کنه. این دیپندنسی نیازه این کاره. دیپندنسی آخرو نمیشناسم حقیقتا دنبالشم نرفتم خودت صفحه گیت‌هابشو بخون.


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



> بخاطر حذف warning های بیلد هست که میتونستن بیخیالشون بشن چون اررور نیستن ولی از این حرفم مطمئن نیستم.


چه ربطی به build داره اگر هم که هشداری تو کتابخانه های گریدل باشه که در زمان سینک کردن خود گریدل پیغام میده.!



> برو مستنداتشو بخون ! الان ولی توصیه میکنم یا از room استفاده کنی یا sql خام بزنی که به مراتب سرعت بیشتری داره. البته باید هوشمندانه انتخاب کنی و بستگی به برنامه و استیج پروژت و محدودیت‌هات داره.


دوست عزیز ممنون به فکر خودم نرسیده بود که برم مستندات شو را بخونم!! من جز اولین کسی هایی بودم که از ORM  های اندروید استفاده کردم تو پروژهام.!
شما به عنوان برنامه نویس آی گپ  تو برنامه کجا ازش استفاده کردید و علتش چی بوده؟



> حدس میزنم آیدی unique میخواستن چون اگه حتی  System.currentTimeMillis یا  nano حتی داخل for بزنی در بعضی شرایط خروجی یکسانی دارن اینقدر for سریع اجرا میشه


دوست عزیز نمی دونم منظورتون از این حرف چی و  استدلالی براش دارید یا نه؟
ولی محض اطلاع نانو تایم از خروجی های زمانبند استفاده میکنه چطور میتونه تکرار بشه که اگر بشه پایپ ها چطور دستورات را اجرا میکنن و کوبیدگی حافظه رخ نمید!.
 و حلقه for  که تو جاوا نوشته میشه داره به یک زبان میانی تفسیر میشه و اجرا میشه حتی مستقیم اجرا نمیشه ! در کدوم پایپ اجرا میشه که سریع تر از نانو تایم زمانبند هست.! 
 خوشحال میشم ببینم که چطوری نانو تایم تکراری میشه تو یک حلقه for.
دوست عزیز اگر کد را اجرا میکردید مشاهده میکردید که به ازای حتی چند ده میلیون بار تکرار بازهم NanoTime 
تکراری نخواهد شد. وبرای اینکه تکنیک های defensive  را هم رعایت کرده باشند اومدن با استفاده از bit vector mask  خروجی currentTimeMillis را در صورت تکرار منحصر بفرد کردند.
 البته  در صورتی که  در حلقه for  هیچ دستوری برای پردازش وجود نداشته باشه شاید در برخی موارد currentTimeMillis خروجی تکراری تولید کنه ولی nanoTime  بعید بنظر میرسه.
 به هر حال قصد من برای خواستن توضیح کدهای آی گپ برای کمک کردن بود نیازی به جبهه گرفتن نبود یعنی حداقل من خودم اگر روزی ادعا بکنم که برنامه نویس فلان برنامه هستم مطمئنا سعی میکردم که جواب هایی که میدم منطقی و شفاف باشه وگرنه من از سال 1378 دارم با سی و هم خانواده اش کد میزنیم اگر هم حرفی زدم بابت تجربه است به کسی بر نخوره بدون غرض بوده.
و از پاسخ های بسیار سطح پایینی که حتی در حد یک کپی و پیست ساده از منبع اصلی هم نبود تشکر! سعی کنید اول یکم بیشتر تحقیق کنید تا حداقل یک پاسخ معتبر تر ارائه میکردید البته این برای این عرض کردم که چون شما خیلی در این سایت فعالیت ندارید شاید بی خبر باشید که اغلب کسانی که اینجا هستند خیلی وقته برنامه نویس هستند و کاربر تازه وارد نیستند.
امان از خود گیک پنداری در برنامه نویس ها...

----------


## farhad_shiri_ex

> configurations.all {
>     resolutionStrategy.eachDependency { DependencyResolveDetails details ->
>         def requested = details.requested
>         if (requested.group == 'com.android.support') {
>             if (!requested.name.startsWith("multidex")) {
>                 details.useVersion '26.0.2'
>             }
>         }
>     }
> ...


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

def _BuildToolsVersionCode = '26.1.1'
implementation 'com.android.support:appcompat-v7:'+_BuildToolsVersionCode

اگر اینطوره که باگ به وجود میاد یعنی اگر نسخه پایینتری از compile sdk version   تو این متغیر قرار بدیم دیگه گریدل هشداری نمیده .
در صورتی که گریدل خودش در زمان سینک کردن پروژه اگر tools version  و compile sdk  یکسان نباشه خطا تولید میکنه که با روش بالا دیگه نمیتونه این خطا را تولید کنه.
پس اگر به صورت دستی نسخه ها ی کتابخانه ها وارد شوند بهینه تر هست حتی در آخرین مستندات گوگل هم اشاره شده که از علامت + هم در tools version   های کتابخانه ها استفاه نکنید. 
حالا بنظر شما وقتی داریم صریح اعلام میکنیم که چه نسخه ای از کتابخانه را می خواهیم دیگه چه نیازی به این تکه کد بوده که در گریدل فایل پروژه آی گپ استفاده بشه.


configurations.all {
    resolutionStrategy.eachDependency { DependencyResolveDetails details ->
        def requested = details.requested
        if (requested.group == 'com.android.support') {
            if (!requested.name.startsWith("multidex")) {
                details.useVersion '27.1.1'
            }
        }
    }
}


البته میتونیم در زمان فراخوانی یک کتابخانه اندروید صریحا ورژن کد build tools  را هم تعریف نکنیم  خود گریدل آخرین نسخه موجود build tools  برای compile sdk version  را که در پروژه انتخاب کردید را سینک خواهد کرد.
یعنی کاری که همین تکه کد بالا در گریدل انجام میده در صورتی که نخواهیم صراحتا build tools version   را در اعلان کتابخانه وارد کنیم باید از تکه کد بالا استفاده کنیم.

----------


## Nevercom

خیر، من به این شکل استفاده می‌کنم:
ext.supportLibraryVersion = "27.0.1"...
implementation "com.android.support:exifinterface:$supportLibrary  Version"
و Lint می‌تونه مقدار رو بخونه و هشدار میده اگه نسخه‌ش ناسازگار باشه یا هرچیز دیگه.

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



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


به همین دلیل که من بجای مستقیم نوشتن نسخه‌ها، از متغیر استفاده می‌کنم. یه وقتایی هست که مجبوری هی نسخه‌ها رو دستکاری کنی تا مشکل بیلد برطرف بشه، تغییر یک متغیر خیلی راحت تر از تغییر چندین خط کد هست. 




> البته میتونیم در زمان فراخوانی یک کتابخانه اندروید صریحا ورژن کد build tools را هم تعریف نکنیم خود گریدل آخرین نسخه موجود build tools برای compile sdk version را که در پروژه انتخاب کردید را سینک خواهد کرد.
> یعنی کاری که همین تکه کد بالا در گریدل انجام میده در صورتی که نخواهیم صراحتا build tools version را در اعلان کتابخانه وارد کنیم باید از تکه کد بالا استفاده کنیم.


چیزی که من در این تکه کد می‌بینم کاری به نسخه‌ی BuildTools نداره و فقط نسخه‌ی Dependency ها رو تغییر میده

----------


## farhad_shiri_ex

ext.supportLibraryVersion = "27.0.1"...
implementation "com.android.support:exifinterface:$supportLib  rary  Version"

چه فرقی داره شما property تعریف کردید من با متغیر نوشته بودم تو پست قبل در همین حالتی هم که شما تعریف کردید بازهم با تغییر در ورژن در صورت یکسان نبودن با compile sdk به من که خطایی نمیده نه در Design ونه در Compile ولی با استفاده از اون تکه کد حداقل در زمان sync کزدن خطا میده

----------


## error_au

سلام به همگی
خوب نظر شما راه کار چیست چه کار باید انجام داد ؟

----------

