এক ডিভাইসে কন্টেন্টপ্রাইডার ব্যবহার করে একই অ্যাপ্লিকেশন চালানোর জন্য গ্রেডলে বিল্ড প্রকারগুলি ব্যবহার করে


124

আমি আমার ডিবাগ অ্যাপ্লিকেশনটিতে প্যাকেজ নামের প্রত্যয় যুক্ত করতে গ্র্যাডল সেট আপ করেছি যাতে আমি প্রকাশিত সংস্করণটি পেতে পারি যা আমি একটি ফোনে সংস্করণটি ডিবাগ করছি এবং ডিবাগ করব। আমি এটি উল্লেখ করছি: http://tools.android.com/tech-docs/new-build-system/user-guide#TOC- বিল্ড- টিপস

আমার বিল্ড.gradle ফাইলটি দেখতে এমন দেখাচ্ছে:

...
android
{
    ...
    buildTypes
    {
        debug
        {
            packageNameSuffix ".debug"
            versionNameSuffix " debug"
        }
    }
}

যতক্ষণ না আমি আমার অ্যাপ্লিকেশনটিতে কন্টেন্টপ্রাইডার ব্যবহার শুরু করি সবকিছু ঠিকঠাক কাজ করে। আমি পাই:

Failure [INSTALL_FAILED_CONFLICTING_PROVIDER]

আমি বুঝতে পারি যে এটি ঘটে কারণ দুটি অ্যাপস (রিলিজ এবং ডিবাগ) একই কন্টেন্টপ্রাইডার কর্তৃপক্ষ নিবন্ধিত করছে।

আমি এটি সমাধান করার একটি সম্ভাবনা দেখছি। যদি আমি সঠিকভাবে বুঝতে পারি তবে আপনি বিল্ডিংয়ের সময় বিভিন্ন ফাইল ব্যবহার করার জন্য নির্দিষ্ট করতে সক্ষম হবেন। তারপরে আমার আলাদা রিসোর্স ফাইলে (এবং ম্যানিফেস্ট সেট কর্তৃপক্ষ থেকে স্ট্রিং রিসোর্স হিসাবে) আলাদা আলাদা কর্তৃপক্ষকে রাখতে এবং গ্রেডলকে ডিবাগ বিল্ডের জন্য বিভিন্ন সংস্থান ব্যবহার করতে বলার পক্ষে সক্ষম হওয়া উচিত। এটা কি সম্ভব? যদি হ্যাঁ হয় তবে কীভাবে এটি অর্জন করতে হবে তার কোনও ইঙ্গিত কী দুর্দান্ত!

অথবা সম্ভবত গ্র্যাডল ব্যবহার করে সরাসরি ম্যানিফেস্টটি সংশোধন করা সম্ভব? একটি ডিভাইসে কন্টেন্টপ্রাইডার দিয়ে কীভাবে একই অ্যাপ্লিকেশনটি চালানো যায় সে সম্পর্কে অন্য কোনও সমাধান সর্বদা স্বাগত।


এই ব্যবহারের ক্ষেত্রে আপস্ট्रीम সমর্থন ট্র্যাক করতে আগ্রহী তাদের জন্য: এওএসপি বাগ রিপোর্ট । "অফিসিয়াল" বর্তমান অবস্থানটি ম্যানিফেস্টের ওভাররাইডিং সমাধানটি ব্যবহার করা ।
দেশীম

উত্তর:


226

বিদ্যমান উত্তরগুলির কোনওটিই আমাকে সন্তুষ্ট করেনি, তবে লিবার্টিটি খুব কাছে ছিল। সুতরাং আমি এই এটি কিভাবে করছি। এই মুহুর্তে সবার সাথে আমি কাজ করছি:

  • অ্যান্ড্রয়েড স্টুডিও বিটা 0.8.2
  • গ্রেডেল প্লাগইন 0.12। +
  • গ্রেডল 1.12

আমার লক্ষ্য চালানো হয় Debugবরাবর সংস্করণ Releaseএকই ডিভাইসে একই ব্যবহার করে সংস্করণ ContentProvider


ইন build.gradle ডিবাগ বিল্ড জন্য আপনার অ্যাপের সেট প্রত্যয়:

buildTypes {
    debug {
        applicationIdSuffix ".debug"
    }
}

ইন Andro আইডি ফাইল সেট android:authoritiesআপনার সম্পত্তি ContentProvider:

<provider
    android:name="com.example.app.YourProvider"
    android:authorities="${applicationId}.provider"
    android:enabled="true"
    android:exported="false" >
</provider>

আপনার কোড সেট AUTHORITYসম্পত্তিতে যা আপনার প্রয়োগের জন্য যেখানে প্রয়োজন সেখানে ব্যবহার করা যেতে পারে:

public static final String AUTHORITY = BuildConfig.APPLICATION_ID + ".provider";

পরামর্শ: আগে ছিলBuildConfig.PACKAGE_NAME

এটাই! এটি একটি মোহন মত কাজ করবে। আপনি যদি SyncAdapter ব্যবহার করেন তবে পড়তে থাকুন!


সিঙ্কএডাপ্টারের জন্য আপডেট (14.11.2014)

আবার আমি আমার বর্তমান সেটআপ দিয়ে শুরু করব:

  • অ্যান্ড্রয়েড স্টুডিও বিটা 0.9.2
  • গ্রেডল প্লাগইন 0.14.1
  • গ্রেডেল 2.1

মূলত, আপনার যদি বিভিন্ন বিল্ডের জন্য কিছু মান কাস্টমাইজ করতে হয় তবে আপনি এটি বিল্ডড্রেডল ফাইল থেকে করতে পারেন:

  • এটি ক্লাস থেকে অ্যাক্সেস করতে বিল্ডকনফিগফিল্ড ব্যবহার করুনBuildConfig.java
  • এটি থেকে উত্স অ্যাক্সেস করতে রেজওয়ালিউ ব্যবহার করুন যেমন @ স্ট্রিং / আপনার_মূল্য

সংস্থানগুলির বিকল্প হিসাবে, আপনি পৃথক বিল্ডটাইপ বা স্বাদ ডিরেক্টরি তৈরি করতে পারেন এবং সেগুলির মধ্যে এক্সএমএল বা মানগুলি ওভাররাইড করতে পারেন। তবে আমি নীচের উদাহরণে এটি ব্যবহার করতে যাচ্ছি না।

উদাহরণ


ইন build.gradle ফাইলের মধ্যে নিম্নলিখিত যোগ করুন:

defaultConfig {
    resValue "string", "your_authorities", applicationId + '.provider'
    resValue "string", "account_type", "your.syncadapter.type"
    buildConfigField "String", "ACCOUNT_TYPE", '"your.syncadapter.type"'
}

buildTypes {
    debug {
        applicationIdSuffix ".debug"
        resValue "string", "your_authorities", defaultConfig.applicationId + '.debug.provider'
        resValue "string", "account_type", "your.syncadapter.type.debug"
        buildConfigField "String", "ACCOUNT_TYPE", '"your.syncadapter.type.debug"'
    }
}

আপনি বিল্ডকনফিগ.জভা ক্লাসে ফলাফল দেখতে পাবেন

public static final String ACCOUNT_TYPE = "your.syncadapter.type.debug";

এবং বিল্ড / জেনারেট / রেজ / জেনারেট / ডিবাগ / ভ্যালু / জেনারেট.এক্সএমএল

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <!-- Automatically generated file. DO NOT MODIFY -->
    <!-- Values from default config. -->
    <item name="account_type" type="string">your.syncadapter.type.debug</item>
    <item name="authorities" type="string">com.example.app.provider</item>

</resources>

আপনার প্রমাণীকরণে। এক্সএমএল বিল্ড.gradle ফাইলটিতে নির্দিষ্ট সংস্থান ব্যবহার করুন

<?xml version="1.0" encoding="utf-8"?>
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
                       android:accountType="@string/account_type"
                       android:icon="@drawable/ic_launcher"
                       android:smallIcon="@drawable/ic_launcher"
                       android:label="@string/app_name"
/>

আপনার syncadapter.xml একই রিসোর্স আবার ব্যবহার এবং @ স্ট্রিং / কর্তৃপক্ষ খুব

<?xml version="1.0" encoding="utf-8"?>
<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
              android:contentAuthority="@string/authorities"
              android:accountType="@string/account_type"
              android:userVisible="true"
              android:supportsUploading="false"
              android:allowParallelSyncs="false"
              android:isAlwaysSyncable="true"
        />

টিপ: স্বতঃপূরণ (Ctrl + স্পেস) এই উত্পন্ন উত্সগুলির জন্য কাজ করে না তাই আপনাকে সেগুলি ম্যানুয়ালি টাইপ করতে হবে


7
সেরা উত্তর আইএমএইচও। খুব ছোট এবং সহজ উদাহরণ।
rekire

হ্যাঁ, আমি এ পর্যন্ত দেখলাম এটি সেরাতম কাজ। ভাগ করে নেওয়ার জন্য আপনাকে অনেক ধন্যবাদ! নতুন প্যাকেজের নামটি ব্যবহার করার জন্য আমার পছন্দসই। এক্সএমএল ফাইলটিতে একটি স্পষ্ট ইনটেন্ট আপডেট করতে হবে বলে এখনও এর সাথে আরও একটি সমস্যা সম্পর্কিত নয়। কোড.google.com/p/android/issues/detail?id=57460
Bernd এস

@ বারেন্ডস আমি সমাধান সহ আপনার ইস্যুতে একটি মন্তব্য পোস্ট করেছি। আপনার বুঝতে হবে যে অ্যাপ্লিকেশন পরিবর্তন করে এটি প্রতিস্থাপন বা প্রত্যয় সেট করে জাভা প্যাকেজগুলি প্রভাবিত করে না। এটি আপনার অ্যাপ্লিকেশনটির কেবলমাত্র শনাক্তকারী এবং এটি জাভা প্যাকেজগুলি থেকে decoupled। অপর এক প্রশ্নের আমার উত্তর দেখুন stackoverflow.com/questions/24178007/...
ড্যামিয়েন Petla

1
@ জেজেডি আপনি যে সংশোধনগুলির সাথে লিঙ্ক করেছেন সেটি কোনও কাস্টম বিল্ড স্ক্রিপ্ট ছাড়াই কাজ করবে। আপনি যদি sync_adapter.xML, ator {applicationId} স্থানধারক ব্যবহার করতে চান, খালিটি.এক্সএমএল আপনার বিল্ড.gradle স্ক্রিপ্টটি কাস্টমাইজ করতে হবে। আমি দেখতে পাচ্ছি যে আপনি ইতিমধ্যে আপনার বিল্ড.gradle স্ক্রিপ্টে অনেক কিছু করেছেন যাতে আপনি ধারণাটি নিয়ে আরামদায়ক হন। আপনি কি আমার উত্তরের নির্দেশাবলী অনুসরণ করেছিলেন এবং এখনও এটি কার্যকর হয়নি?
রব মিউউইস

1
সিঙ্কাডাপ্টারের জন্য কীভাবে তা দিয়ে আমি আমার উত্তর আপডেট করেছি
দামিয়ান পেটলা

39

নতুন অ্যান্ড্রয়েড বিল্ড সিস্টেম টিপ: কন্টেন্টপ্রোভাইডার কর্তৃপক্ষের নামকরণ

আমার অনুমান যে আপনারা সকলেই নতুন অ্যান্ড্রয়েড গ্রেডল ভিত্তিক বিল্ড সিস্টেমটি শুনেছেন। আসুন সত্যি কথা বলতে, এই নতুন বিল্ড সিস্টেমটি আগেরটির তুলনায় এক বিশাল পদক্ষেপ। এটি এখনও চূড়ান্ত হয়নি (এই লেখার হিসাবে, সর্বশেষ সংস্করণটি 0.4.2) তবে আপনি ইতিমধ্যে আপনার বেশিরভাগ প্রকল্পে এটি নিরাপদে ব্যবহার করতে পারেন।

আমি ব্যক্তিগতভাবে আমার বেশিরভাগ প্রকল্প এই নতুন বিল্ড সিস্টেমে স্যুইচ করেছি এবং কিছু বিশেষ পরিস্থিতিতে সমর্থন না পাওয়ার কারণে কিছু সমস্যা ছিল had যার মধ্যে একটি বিষয়বস্তু সরবরাহকারী কর্তৃপক্ষের নামকরণের জন্য সমর্থন

নতুন অ্যান্ড্রয়েড বিল্ট সিস্টেম আপনাকে নির্মানের সময় প্যাকেজের নামটি কেবল সংশোধন করে আপনার অ্যাপের বিভিন্ন ধরণের মোকাবেলা করতে দেয়। এই উন্নতির অন্যতম প্রধান সুবিধা হ'ল আপনি এখন একই অ্যাপ্লিকেশনটির দুটি ভিন্ন সংস্করণ একই ডিভাইসে ইনস্টল করতে পারেন। এই ক্ষেত্রে:

android {
   compileSdkVersion 17
   buildToolsVersion "17.0.0"

   defaultConfig {
       packageName "com.cyrilmottier.android.app"
       versionCode 1
       versionName "1"
       minSdkVersion 14 // Listen to +Jeff Gilfelt advices :)
       targetSdkVersion 17
   }

   buildTypes {
       debug {
        packageNameSuffix ".debug"
            versionNameSuffix "-debug"
       }
   }
}

এই ধরনের গ্রেডল কনফিগারেশন ব্যবহার করে আপনি দুটি পৃথক এপিপি একত্র করতে পারেন:

। Com.cyrilmottier.android.app.debug প্যাকেজের নাম সহ একটি ডিবাগ এপিকে •

এটির সাথে একমাত্র সমস্যা হ'ল যদি তারা উভয়ই একই কর্তৃপক্ষের সাথে একটি সামগ্রী প্রচার সরবরাহ করে তবে আপনি দুটি এপিপি একই সাথে ইনস্টল করতে পারবেন না। অত্যন্ত যৌক্তিকভাবে আমাদের বর্তমান বিল্ড ধরণের উপর নির্ভর করে কর্তৃপক্ষের নাম পরিবর্তন করতে হবে ... তবে এটি গ্রেডল বিল্ড সিস্টেম দ্বারা সমর্থিত নয় (এখনও? ... আমি নিশ্চিত যে খুব শীঘ্রই এটি ঠিক হয়ে যাবে)। সুতরাং এখানে যাওয়ার একটি উপায়:

প্রথমে আমাদের সরবরাহকারীর অ্যান্ড্রয়েড ম্যানিফেস্ট কনটেন্টপ্রোভাইডার ঘোষণাকে যথাযথ বিল্ড টাইপে স্থানান্তরিত করতে হবে। এটি করার জন্য আমাদের সহজভাবে থাকবে:

src / ডিবাগ / Andro আইডি

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="com.cyrilmottier.android.app"
   android:versionCode="1"
   android:versionName="1">

   <application>

       <provider
           android:name=".provider.Provider1"
           android:authorities="com.cyrilmottier.android.app.debug.provider"
           android:exported="false" />

   </application>
</manifest>

src / রিলিজ / Andro আইডি

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="com.cyrilmottier.android.app"
   android:versionCode="1"
   android:versionName="1">

   <application>

       <provider
           android:name=".provider.Provider1"
           android:authorities="com.cyrilmottier.android.app.provider"
           android:exported="false" />

   </application>
</manifest>

Src / main / এ AndroidManLive.xML থেকে কন্টেন্টপ্রভাইডার ঘোষণাটি সরিয়ে ফেলার বিষয়ে নিশ্চিত হন / কারণ গ্রেডল জানেন না কীভাবে একই নামযুক্ত একটি পৃথক কর্তৃপক্ষ রয়েছে তবে কীভাবে কনটেন্টপ্রভাইডারগুলিকে একীভূত করতে হয়।

শেষ পর্যন্ত আমাদের কোডে কর্তৃপক্ষের অ্যাক্সেসের প্রয়োজন হতে পারে। বিল্ডকনফিগ ফাইল এবং বিল্ডকনফিগ পদ্ধতিটি ব্যবহার করে এটি খুব সহজেই করা যায়:

android {   
   // ...

    final PROVIDER_DEBUG = "com.cyrilmottier.android.app.debug.provider"
    final PROVIDER_RELEASE = "com.cyrilmottier.android.app.provider"

   buildTypes {
       debug {
           // ...
           buildConfigField "String", "PROVIDER_AUTHORITY", PROVIDER_DEBUG
       }

       release {
           buildConfigField "String", "PROVIDER_AUTHORITY", PROVIDER_RELEASE
       }
   }
}

এই কাজের জন্য ধন্যবাদ আপনি বিল্ডকনফাইগ ব্যবহার করতে সক্ষম হবেন। প্র্রোভিডER_AUTHORITY আপনার সরবরাহকারী চুক্তিতে এবং একই সাথে আপনার অ্যাপ্লিকেশনের দুটি পৃথক সংস্করণ ইনস্টল করতে পারবেন।


Google+ এ মূল: https://plus.google.com/u/0/118417777153109946393/posts/EATUmhntaCQ


1
এমন কারও জন্য যা গ্রেড চালাতে পারে না, সিনট্যাক্সির ত্রুটিটিকে পিছনে ফেলে দিন। উত্তরটি এখানে: স্ট্যাকওভারফ্লো
রেনান ফ্রাঙ্কা

23

আপনার যদি কেবল কয়েকটি বিল্ড প্রকার থাকে তবে সিরিলের উদাহরণ দুর্দান্ত কাজ করে, আপনার যদি অনেকগুলি অ্যান্ড্রয়েড ম্যানিফেস্ট.এক্সএমএল প্রচুর বজায় রাখতে হয় তবে আপনার কাছে অনেকগুলি বিল্ড প্রকার এবং / অথবা পণ্যগুলির স্বাদ থাকলে তা দ্রুত জটিল হয়ে যায়।

আমাদের প্রকল্পে 3 টি বিল্ড প্রকার এবং 6 টি স্বাদযুক্ত মোট 18 টি বিল্ড ভেরিয়েন্ট রয়েছে, সুতরাং এর পরিবর্তে আমরা কন্টেন্টপ্রাইডার কর্তৃপক্ষগুলিতে ".res-auto" এর জন্য সমর্থন যোগ করেছি, যা বর্তমান প্যাকেজটির কাছে প্রসারিত হয় এবং বিভিন্ন অ্যান্ড্রয়েড ম্যানিফেস্ট.এক্সএমএল বজায় রাখার প্রয়োজনীয়তা সরিয়ে দেয়

/**
 * Version 1.1.
 *
 * Add support for installing multiple variants of the same app which have a
 * content provider. Do this by overriding occurrences of ".res-auto" in
 * android:authorities with the current package name (which should be unique)
 *
 * V1.0 : Initial version
 * V1.1 : Support for ".res-auto" in strings added, 
 *        eg. use "<string name="auth">.res-auto.path.to.provider</string>"
 *
 */
def overrideProviderAuthority(buildVariant) {
    def flavor = buildVariant.productFlavors.get(0).name
    def buildType = buildVariant.buildType.name
    def pathToManifest = "${buildDir}/manifests/${flavor}/${buildType}/AndroidManifest.xml"

    def ns = new groovy.xml.Namespace("http://schemas.android.com/apk/res/android", "android")
    def xml = new XmlParser().parse(pathToManifest)
    def variantPackageName = xml.@package

    // Update all content providers
    xml.application.provider.each { provider ->
        def newAuthorities = provider.attribute(ns.authorities).replaceAll('.res-auto', variantPackageName)
        provider.attributes().put(ns.authorities, newAuthorities)
    }

    // Save modified AndroidManifest back into build dir
    saveXML(pathToManifest, xml)

    // Also make sure that all strings with ".res-auto" are expanded automagically
    def pathToValues = "${buildDir}/res/all/${flavor}/${buildType}/values/values.xml"
    xml = new XmlParser().parse(pathToValues)
    xml.findAll{it.name() == 'string'}.each{item ->
        if (!item.value().isEmpty() && item.value()[0].startsWith(".res-auto")) {
            item.value()[0] = item.value()[0].replace(".res-auto", variantPackageName)
        }
    }
    saveXML(pathToValues, xml)
}

def saveXML(pathToFile, xml) {
    def writer = new FileWriter(pathToFile)
    def printer = new XmlNodePrinter(new PrintWriter(writer))
    printer.preserveWhitespace = true
    printer.print(xml)
}

// Post processing of AndroidManifest.xml for supporting provider authorities
// across build variants.
android.applicationVariants.all { variant ->
    variant.processManifest.doLast {
        overrideProviderAuthority(variant)
    }
}

উদাহরণ কোডটি এখানে পাওয়া যাবে: https://gist.github.com/cmelchior/6988275


আমি আমার প্রকল্পের জন্যও খুব অনুরূপ কিছু ব্যবহার করতে চলেছি কারণ বিল্ড ফ্লেভারগুলির সাথে আমার একই সমস্যা ছিল। এই পদ্ধতির আপাতত খুব ভাল কাজ করে।
মান্টাসভি

2
ফাইল রাইটার কমপক্ষে আমার ম্যাক ওএস-এ, utf-8 ফাইলগুলিতে সমস্যা তৈরি করে। আমি সম্পর্কিত লাইনটি এতে পরিবর্তন করেছি: ডিএফ লেখক = নতুন আউটপুট স্ট্রিম রাইটার (নতুন ফাইলআউটপুটস্ট্রিম (পাথটো ফাইল), "ইউটিএফ -8")
রেজা মোহাম্মদী

এটি সত্যিই দুর্দান্ত, আপনাকে ধন্যবাদ! বিন্যাসিত স্ট্রিংগুলির সাথে ভাঙ্গন রোধ করতে আমি একটি ছোট পরিবর্তন করেছি। gist.github.com/paour/8475929
পিয়েরে-লুক পাওর 17'14

এটি খুব সহায়ক ছিল, তবে আমি এমন একটি সমস্যায় পড়ে গেলাম যেখানে এটি পরিষ্কারের পরে তৈরি হবে না কারণ প্রক্রিয়া ম্যানিফেস্ট পর্যায়ে বিল্ড ফোল্ডারে কোনও মানের.xML ফাইল নেই। প্রক্রিয়া রিসোর্স পর্যায়ে অস্তিত্ব নেই, যার ম্যানিফেস্টটি সংশোধন করতে খুব দেরী হয়েছে, সুতরাং ম্যানিফেস্ট এবং মান উভয় ফাইলের মধ্যে .res- অটো প্রতিস্থাপন করতে আমার মনে হয় আপনার দুটি ফাংশন প্রয়োজন যা ভেরিয়েন্ট দ্বারা ডাকা হয়। প্রক্রিয়া ম্যানিফেস্ট.ডোস্টাল, অন্যটি বৈকল্পিক.প্রসেসরেসোর্স.ডোস্ট দ্বারা ডাকা হয়েছে ast
নিয়াল

20

যেহেতু প্লাগইন সংস্করণ 0.8.3 (আসলে 0.8.1 তবে এটি সঠিকভাবে কাজ করছে না) আপনি বিল্ড ফাইলের মধ্যে সংস্থানগুলি সংজ্ঞায়িত করতে পারেন তাই এটি একটি ক্লিনার সমাধান হতে পারে কারণ আপনার স্ট্রিং ফাইল বা অতিরিক্ত ডিবাগ / প্রকাশের প্রয়োজন নেই don't ফোল্ডার নেই।

build.gradle

android {
    buildTypes {
        debug{
            resValue "string", "authority", "com.yourpackage.debug.provider"
        }
        release {
            resValue "string", "authority", "com.yourpackage.provider"
        }
    }
}

Andro আইডি

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="com.yourpackage"
   android:versionCode="1"
   android:versionName="1">

   <application>

       <provider
           android:name=".provider.Provider1"
           android:authorities="@string/authority"
           android:exported="false" />

   </application>
</manifest>

2
সাবধান, রিসোর্স-ভিত্তিক কর্তৃপক্ষগুলি কেবল অ্যান্ড্রয়েড ২.২.১ এবং তার পরে কাজ করে: github.com/android/platform_frameworks_base/commit/…
পিয়ের-লাক পাওর

স্পষ্টতার জন্য ধন্যবাদ।
rciovati

1
এটি অ্যান্ড্রয়েডের জন্য অনুসন্ধানযোগ্য.এক্সএমএল: সার্চসোজেস্টঅর্টিগ্রিটির ক্ষেত্রেও খুব দরকারী, কারণ সেখানে আপনি :
26

13

কারও উল্লেখ আছে কিনা জানি না। আসলে পর অ্যান্ড্রয়েড gradle প্লাগইন 0.10+, উদ্ভিন্ন সমবায় এই ফাংশন জন্য সরকারী সহায়তা প্রদান করা হবে: http://tools.android.com/tech-docs/new-build-system/user-guide/manifest-merger

অ্যান্ড্রয়েডম্যানিফেস্ট.এক্সএমএলে, আপনি এই জাতীয় {{প্যাকেজনাম use ব্যবহার করতে পারেন:

<provider
    android:name=".provider.DatabasesProvider"
    android:authorities="${packageName}.databasesprovider"
    android:exported="true"
    android:multiprocess="true" />

এবং আপনার বিল্ড.gradle এ আপনি থাকতে পারেন:

productFlavors {
    free {
        packageName "org.pkg1"
    }
    pro {
        packageName "org.pkg2"
    }
}

এখানে সম্পূর্ণ উদাহরণ দেখুন: https://code.google.com/p/anymemo/source/browse/AndroidManLive.xml#152

এবং এখানে: https://code.google.com/p/anymemo/source/browse/build.gradle#41


এটি দুর্দান্ত খবর, তবে এটি <সন্ধানযোগ্য> উপাদানগুলির ক্ষেত্রে এটি সম্পূর্ণ সমাধান বলে মনে হচ্ছে না যা অটোরিটির রেফারেন্স করা দরকার, যেহেতু এগুলি ম্যানিফেস্টের অংশ নয় (তবে বিদ্যমান মার্জ কৌশলগুলি এই ফাইলগুলির জন্য কাজ করে, ম্যানিফেস্টের বিপরীতে)।
পিয়েরে-লুক পাওর

1
এর জন্য আপনাকে স্বাদ ব্যবহার করতে হবে না, এটি বিল্ড টাইপগুলির সাথেও কাজ করে। এছাড়াও, আপনার প্যাকেজটির স্থিতিশীল রেফারেন্স পেতে আপনি বিল্ডকনফিগ.প্যাকক্যাগ কে ব্যবহার করতে পারেন তা উল্লেখ করে ভাল লাগবে। এটি সামগ্রীর সরবরাহকারীদের জন্য দরকারী যেখানে সামগ্রী সরবরাহকারীকে জিজ্ঞাসা করার জন্য রানটাইমগুলিতে কর্তৃপক্ষের জানা দরকার।
ম্যাট ওল্ফ

1
অ্যান্ড্রয়েডের জন্য {{প্যাকেজনাম} এর পরিবর্তে {{অ্যাপ্লিকেশনআইডি use ব্যবহার করার জন্যও আপডেট করা উচিত: কর্তৃপক্ষ
বার্নড এস

8

${applicationId}এক্সএমএল এবং BuildConfig.APPLICATION_IDকোডে স্থানধারক ব্যবহার করুন ।

ম্যানিফেস্ট ব্যতীত অন্য এক্সএমএল ফাইলগুলিতে স্থানধারকদের সক্ষম করতে আপনাকে বিল্ড স্ক্রিপ্টটি প্রসারিত করতে হবে। এক্সএমএল ফাইলের বিভিন্ন সংস্করণ সরবরাহ করতে আপনি প্রতি বিল্ড ভেরিয়েন্টের উত্স ডিরেক্টরি ব্যবহার করতে পারেন তবে রক্ষণাবেক্ষণ খুব দ্রুত জটিল হয়ে উঠবে।

Andro আইডি

আপনি ম্যানিফেস্টে বক্সের বাইরে অ্যাপ্লিকেশনআইড প্লেসোল্ডার ব্যবহার করতে পারেন। আপনার সরবরাহকারীকে এটির মতো ঘোষণা করুন:

<provider
    android:name=".provider.DatabaseProvider"
    android:authorities="${applicationId}.DatabaseProvider"
    android:exported="false" />

${applicationId}বিট নোট করুন । এটি নির্মাণের সময় প্রকৃত প্রয়োগের সাথে প্রতিস্থাপন করা হবে যা তৈরি হচ্ছে সেই বিল্ড বৈকল্পিকের জন্য।

কোডে

আপনার বিষয়বস্তু সরবরাহকারীকে কোডে কর্তৃত্বের স্ট্রিং তৈরি করতে হবে। এটি বিল্ডকনফিগ শ্রেণি ব্যবহার করতে পারে।

public class DatabaseContract {
    /** The authority for the database provider */
    public static final String AUTHORITY = BuildConfig.APPLICATION_ID + ".DatabaseProvider";
    // ...
}

BuildConfig.APPLICATION_IDবিট নোট করুন । এটি প্রকৃত অ্যাপ্লিকেশন সহ একটি উত্পন্ন শ্রেণি যা বিল্ড বৈকল্পিক নির্মিত হচ্ছে for

রেস / এক্সএমএল / ফাইলগুলি, যেমন সিঙ্কাডাপ্টার.এক্সএমএল, অ্যাকাউন্টআউটথ্যান্টিকেটর.এক্সএমএল

আপনি যদি একটি সিঙ্ক অ্যাডাপ্টার ব্যবহার করতে চান তবে আপনাকে res / xML / ডিরেক্টরিতে এক্সএমএল ফাইলগুলিতে কন্টেন্টপ্রোভাইডার এবং অ্যাকাউন্ট ম্যানেজারের জন্য মেটা-ডেটা সরবরাহ করতে হবে। অ্যাপ্লিকেশনআইডির স্থানধারক এখানে সমর্থিত নয়। এটিকে হ্যাক করার জন্য আপনি নিজে বিল্ড স্ক্রিপ্টটি প্রসারিত করতে পারেন।

<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
    android:accountType="${applicationId}"
    android:allowParallelSyncs="false"
    android:contentAuthority="${applicationId}.DatabaseProvider"
    android:isAlwaysSyncable="true"
    android:supportsUploading="true"
    android:userVisible="true" />

<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
    android:accountType="${applicationId}"
    android:icon="@drawable/ic_launcher"
    android:label="@string/account_authenticator_label"
    android:smallIcon="@drawable/ic_launcher" />

আবার, নোট করুন ${applicationId}। এটি কেবলমাত্র যদি আপনি নীচের গ্রেড স্ক্রিপ্টটিকে আপনার মডিউলটির মূলটিতে যোগ করেন এবং build.gradle থেকে প্রয়োগ করেন তবে এটি কাজ করে।

build.gradle

মডিউল build.gradle স্ক্রিপ্ট থেকে অতিরিক্ত বিল্ড স্ক্রিপ্ট প্রয়োগ করুন। একটি ভাল জায়গা অ্যান্ড্রয়েড গ্রেড প্লাগইনের নীচে।

apply plugin: 'com.android.application'
apply from: './build-processApplicationId.gradle'

android {
    compileSdkVersion 21
    // etc.

বিল্ড-processApplicationId.gradle

নীচে একটি রেজ / এক্সএমএল / স্থানধারক বিল্ড স্ক্রিপ্টের জন্য উত্স কাজ করছে। আরও ভাল ডকুমেন্টেড সংস্করণ গিথুবে উপলভ্য । উন্নতি এবং সম্প্রসারণ স্বাগত welcome

def replace(File file, String target, String replacement) {
    def result = false;

    def reader = new FileReader(file)
    def lines = reader.readLines()
    reader.close()

    def writer = new FileWriter(file)
    lines.each { line ->
        String replacedLine = line.replace(target, replacement)
        writer.write(replacedLine)
        writer.write("\n")
        result = result || !replacedLine.equals(line)
    }
    writer.close()

    return result
}

def processXmlFile(File file, String applicationId) {
    if (replace(file, "\${applicationId}", applicationId)) {
        logger.info("Processed \${applicationId} in $file")
    }
}

def processXmlDir(File dir, String applicationId) {
    dir.list().each { entry ->
        File file = new File(dir, entry)
        if (file.isFile()) {
            processXmlFile(file, applicationId)
        }
    }
}

android.applicationVariants.all { variant ->
    variant.mergeResources.doLast {
        def applicationId = variant.mergedFlavor.applicationId + (variant.buildType.applicationIdSuffix == null ? "" : variant.buildType.applicationIdSuffix)
        def path = "${buildDir}/intermediates/res/${variant.dirName}/xml/"
        processXmlDir(new File(path), applicationId)
    }
}

strings.xml

আমার মতে রিসোর্স স্ট্রিংয়ের জন্য স্থানধারক সমর্থন যুক্ত করার দরকার নেই। উপরের ব্যবহারের ক্ষেত্রে কমপক্ষে এটির দরকার নেই। তবে আপনি সহজেই স্ক্রিপ্টটি পরিবর্তন করতে পারবেন কেবল স্থান / প্রতিস্থাপন / এক্সএমএল / ডিরেক্টরিতে স্থানধারককে প্রতিস্থাপন করতে, কিন্তু পুনরায় আকার / মান / ডিরেক্টরিতেও।


6

আমি বরং সিরিল এবং রিসিওবাতির মধ্যে একটি মিশ্রণ পছন্দ করব। আমি মনে করি আরও সহজ, আপনার কেবল দুটি পরিবর্তন রয়েছে।

build.gradleদেখে মনে হচ্ছে:

android {
    ...
    productFlavors {
        production {
            packageName "package.name.production"
            resValue "string", "authority", "package.name.production.provider"
            buildConfigField "String", "AUTHORITY", "package.name.production.provider"
        }

        testing {
            packageName "package.name.debug"
            resValue "string", "authority", "package.name.debug.provider"
            buildConfigField "String", "AUTHORITY", "package.name.debug.provider"
        }
    }
    ...
}

এবং AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="package.name" >

    <application
        ...>

        <provider android:name=".contentprovider.Provider" android:authorities="@string/authority" />

    </application>
</manifest>

5

gradle.build

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.1"

    defaultConfig {
        applicationId "com.example.awsomeapp"
        minSdkVersion 9
        targetSdkVersion 23
        versionCode 1
        versionName "1.0.0"
    }

    productFlavors
    {
        prod {
            applicationId = "com.example.awsomeapp"
        }

        demo {
            applicationId = "com.example.awsomeapp.demo"
            versionName = defaultConfig.versionName + ".DEMO"
        }
    }

    buildTypes {
        release {
            signingConfig signingConfigs.release
            debuggable false
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }

        debug {
            applicationIdSuffix ".debug"
            versionNameSuffix = ".DEBUG"
            debuggable true
        }
    }

    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            // rename the apk
            def file = output.outputFile;
            def newName;
            newName = file.name.replace(".apk", "-" + defaultConfig.versionName + ".apk");
            newName = newName.replace(project.name, "awsomeapp");
            output.outputFile = new File(file.parent, newName);
        }

        //Generate values Content Authority and Account Type used in Sync Adapter, Content Provider, Authenticator
        def valueAccountType = applicationId + '.account'
        def valueContentAuthority = applicationId + '.authority'

        //generate fields in Resource string file generated.xml
        resValue "string", "content_authority", valueContentAuthority
        resValue "string", "account_type", valueAccountType

        //generate fields in BuildConfig class
        buildConfigField "String", "ACCOUNT_TYPE", '"'+valueAccountType+'"'
        buildConfigField "String", "CONTENT_AUTHORITY", '"'+valueContentAuthority+'"'

        //replace field ${valueContentAuthority} in AndroidManifest.xml
        mergedFlavor.manifestPlaceholders = [ valueContentAuthority: valueContentAuthority ]
    }
}

authenticator.xml

<?xml version="1.0" encoding="utf-8"?>
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
    android:accountType="@string/account_type"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:smallIcon="@drawable/ic_launcher" />

sync_adapter.xml

<?xml version="1.0" encoding="utf-8"?>
<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
              android:contentAuthority="@string/content_authority"
              android:accountType="@string/account_type"
              android:userVisible="true"
              android:allowParallelSyncs="false"
              android:isAlwaysSyncable="true"
              android:supportsUploading="true"/>

Andro আইডি

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0.0" package="com.example.awsomeapp">

    <uses-permission android:name="android.permission.GET_ACCOUNTS"/><!-- SyncAdapter and GCM requires a Google account. -->
    <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/>
    <uses-permission android:name="android.permission.USE_CREDENTIALS"/>

    <!-- GCM Creates a custom permission so only this app can receive its messages. -->
    <permission android:name="${applicationId}.permission.C2D_MESSAGE" android:protectionLevel="signature"/>
    <uses-permission android:name="${applicationId}.permission.C2D_MESSAGE"/>

    <application....
    .......

        <!-- Stub Authenticator --> 
        <service 
                android:name="com.example.awsomeapp.service.authenticator.CAuthenticatorService"
                android:exported="true">
            <intent-filter>
                <action android:name="android.accounts.AccountAuthenticator"/>
            </intent-filter>
            <meta-data android:name="android.accounts.AccountAuthenticator" android:resource="@xml/authenticator"/>
        </service>
        <!--  -->

        <!-- Sync Adapter -->
        <service
                android:name="com.example.awsomeapp.service.sync.CSyncService"
                android:exported="true"
                android:process=":sync">
            <intent-filter>
                <action android:name="android.content.SyncAdapter"/>
            </intent-filter>
            <meta-data android:name="android.content.SyncAdapter" android:resource="@xml/sync_adapter" />
        </service>
        <!--  -->

        <!-- Content Provider -->
        <provider android:authorities="${valueContentAuthority}"
            android:exported="false" 
            android:name="com.example.awsomeapp.database.contentprovider.CProvider">
        </provider>
        <!--  --> 
    </application>
</manifest>

কোড:

public static final String CONTENT_AUTHORITY = BuildConfig.CONTENT_AUTHORITY;
public static final String ACCOUNT_TYPE = BuildConfig.ACCOUNT_TYPE;

4

@ ক্রিশ্চিয়ানমেলচিয়ারের নমুনার ভিত্তিতে, এখানে আমার সমাধানটি দেওয়া হয়েছে, যা পূর্ববর্তী সমাধানগুলিতে দুটি সমস্যা সমাধান করে:

  • সমাধানগুলি যা বিল্ড ডিরেক্টরিতে মানগুলি পরিবর্তন করে x

  • অজানা কারণে, ইন্টেলিজ (এবং সম্ভবত অ্যান্ড্রয়েড স্টুডিও) নির্ভরযোগ্যভাবে সংস্থানগুলি প্রক্রিয়া করে না, যার ফলে বিল্ডটি প্রতিস্থাপনকারী .res-autoসরবরাহকারী কর্তৃপক্ষগুলিকে ধারণ করে

এই নতুন সমাধানটি একটি নতুন কার্য তৈরি করে আরও গ্রেডল পদ্ধতিতে কাজ করে এবং ইনপুট এবং আউটপুট ফাইলগুলি সংজ্ঞায়িত করে ইনক্রিমেন্টাল বিল্ডগুলির অনুমতি দেয় allows

  1. একটি ফাইল তৈরি করুন (উদাহরণস্বরূপ আমি এটি একটি variantsডিরেক্টরিতে রেখেছি ), রিসোর্স এক্সএমএল ফাইলের মতো ফর্ম্যাটেড, এতে স্ট্রিং সংস্থান রয়েছে। এগুলি অ্যাপ্লিকেশানের সংস্থানগুলিতে একীভূত হবে এবং .res-autoমানগুলির যে কোনও ঘটনাকে পরিবর্তকের প্যাকেজের নামের সাথে প্রতিস্থাপন করা হবে, উদাহরণস্বরূপ<string name="search_provider">.res-auto.MySearchProvider</string>

  2. যোগ build_extras.gradleথেকে ফাইল এই সারকথা আপনার প্রকল্পে এবং প্রধান থেকে এটা রেফারেন্স build.gradleযোগ করে apply from: './build_extras.gradle'উপরে কোথাও androidব্লক

  3. নিশ্চিত হয়ে নিন যে আপনি কোনও ডিফল্ট প্যাকেজ নামটি android.defaultConfigব্লকের সাথে যুক্ত করে সেট করেছেনbuild.gradle

  4. মধ্যে AndroidManifest.xmlএবং (যেমন অন্যান্য কনফিগারেশন ফাইল xml/searchable.xmlস্বয়ং-সম্পূর্ণতে অনুসন্ধান প্রদানকারীর জন্য), প্রদানকারী (উদাহরণস্বরূপ উল্লেখ @string/search_provider)

  5. যদি আপনাকে একই নামটি পেতে হয় তবে আপনি BuildConfig.PACKAGE_NAMEচলকটি ব্যবহার করতে পারেন , উদাহরণস্বরূপBuildConfig.PACKAGE_NAME + ".MySearchProvider"

https://gist.github.com/paour/9189462


আপডেট: এই পদ্ধতিটি কেবল অ্যান্ড্রয়েড ২.২.১ এবং তার পরে কাজ করে। পূর্ববর্তী প্ল্যাটফর্মগুলির জন্য, এই উত্তরটি দেখুন , যার নিজস্ব সমস্যার একটি সেট রয়েছে, যেহেতু নতুন ম্যানিফেস্ট মার্জারটি এখনও প্রান্তগুলির চারপাশে খুব রুক্ষ ...


আপনি আপনার ভেরিয়েন্ট ডিরেক্টরি কোথায় রাখছেন? আমার কাছে একটি বড় অ্যান্ড্রয়েড স্টুডিও প্রকল্প রয়েছে যা বেশ কয়েকটি অ্যান্ড্রয়েড মডিউল - আমার প্রধান অ্যাপ্লিকেশন এবং কয়েকটি অ্যান্ড্রয়েড লাইব্রেরি মডিউলগুলির উপর নির্ভর করে। আমি কমান্ড লাইন থেকে তৈরি করতে পারি, তবে যখন আমি অ্যান্ড্রয়েড স্টুডিওর ভিতরে থেকে তৈরি করার চেষ্টা করি তখন এটি variants/res-auto-values.xmlআপেক্ষিকভাবে সন্ধান করে /Applications/Android Studio.app/bin/। অর্থাত্ আমি এর জন্য কোনও ফাইলনটফাউন্ডএক্সেপশন পাই না /Applications/Android Studio.app/bin/variants/res-auto-values.xml। আমি একটি ম্যাক উপর চালাচ্ছি। এটি দুর্দান্ত সমাধান, তবে আমি দলের অন্যান্য সদস্যদের জন্য এটি আইডিইতে কাজ করতে চাই।
ব্যবহারকারী 1978019

1
আমার নিজের সমস্যা স্থির করেছেন। গ্রেডল ব্যবহার করে পাথগুলি সমাধান করার জন্য উপস্থিত হয় System.getProperty("user.dir"), যা অ্যান্ড্রয়েড স্টুডিও বিল্ড দ্বারা চালিত হওয়ার পরে একটি আলাদা ফলাফল দেয়। সমাধানটি হ'ল প্রকল্প ডিরেক্টরি সম্পর্কিত পথটি ব্যবহার করা, যা দিয়ে ফিরে আসে gradle.startParameter.getProjectDir()। পাওরের লিঙ্কযুক্ত টুকরোটিতেও আমার মন্তব্য দেখুন।
ব্যবহারকারী 1978019

সাবধান, রিসোর্স-ভিত্তিক কর্তৃপক্ষগুলি কেবল অ্যান্ড্রয়েড ২.২.১ এবং তার পরে কাজ করে: github.com/android/platform_frameworks_base/commit/…
পিয়ের-লুক পাওর

3

আমি গিথুব নমুনা প্রকল্পের সাথে একটি ব্লগপোস্ট লিখেছি যা এই সমস্যাটিকে (এবং অন্যান্য অনুরূপ সমস্যাগুলি) সিরিলের চেয়ে কিছুটা ভিন্নভাবে মোকাবেলা করে।

http://brad-android.blogspot.com/2013/08/android-gradle-building-unique-build.html


2

দুর্ভাগ্যক্রমে, অ্যান্ড্রয়েড প্লাগইনের বর্তমান সংস্করণ (0.4.1) এর জন্য ভাল সমাধান সরবরাহ করে না বলে মনে হচ্ছে। আমি এখনো এই চেষ্টা করার সময় ছিল না, কিন্তু এই সমস্যার জন্য একটি সম্ভাব্য কার্যসংক্রান্ত একটি স্ট্রিং রিসোর্স ব্যবহার করতে হবে @string/provider_authorityএবং, ব্যবহার এই ম্যানিফেস্টে: android:authority="@string/provider_authority"। তারপরে আপনার res/values/provider.xmlপ্রতিটি বিল্ড প্রকারের রেজোল্ড ফোল্ডারে একটি রয়েছে যা কর্তৃপক্ষকে ওভাররাইড করতে হবে, আপনার ক্ষেত্রে এটি হবেsrc/debug/res

আমি ফ্লাইতে এক্সএমএল ফাইল তৈরির দিকে নজর রেখেছি, তবে আবার, প্লাগইনের বর্তমান সংস্করণে এটির জন্য কোনও ভাল হুক বলে মনে হচ্ছে না। আমি কোনও বৈশিষ্ট্যের অনুরোধটি রাখার পরামর্শ দিচ্ছি তবে, আমি ভাবতে পারি যে আরও মানুষ এই একই সমস্যাটিতে আসবে।


হাই মার্কাস, আপনার উত্তরের জন্য ধন্যবাদ। আপনার প্রস্তাবিত সমাধানটি কেবলমাত্র আমি আপাতত নিজেকে ভাবতে পারি। তবে আমার সমস্যা হ'ল গ্র্যাডলের সাথে কীভাবে তা অর্জন করতে হয় তা আমি জানি না।
মান্টাসভি

2

এই পোস্টে উত্তর আমার জন্য কাজ করে।

http://www.kevinrschultz.com/blog/2014/03/23/using-android-content-providers-with-multiple-package-names/

আমি 3 টি আলাদা স্বাদ ব্যবহার করি তাই কেভিনার্সচাল্টজ বলেছেন যে আমি প্রতিটি স্বাদে সামগ্রী সরবরাহকারীর সাথে 3 ম্যানিফেস্ট তৈরি করি:

productFlavors {
    free {
        packageName "your.package.name.free"
    }

    paid {
        packageName "your.package.name.paid"
    }

    other {
        packageName "your.package.name.other"
    }
}

আপনার প্রধান ম্যানিফেস্টে সরবরাহকারীদের অন্তর্ভুক্ত নয়:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- Permissions -->
<application>
    <!-- Nothing about Content Providers at all -->
    <!-- Activities -->
    ...
    <!-- Services -->
    ...
</application>

এবং সরবরাহকারী সহ আপনার প্রতিটি স্বাদে আপনার ম্যানিফেস্ট।

ফ্রি:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" >
<application>
    <!-- Content Providers -->
    <provider
        android:name="your.package.name.Provider"
        android:authorities="your.package.name.free"
        android:exported="false" >
    </provider>
</application>
</manifest>

পেইড:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" >
<application>
    <!-- Content Providers -->
    <provider
        android:name="your.package.name.Provider"
        android:authorities="your.package.name.paid"
        android:exported="false" >
    </provider>
</application>
</manifest>

অন্য:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" >
<application>
    <!-- Content Providers -->
    <provider
        android:name="your.package.name.Provider"
        android:authorities="your.package.name.other"
        android:exported="false" >
    </provider>
</application>
</manifest>


0

আমার সমাধানটি হ'ল স্থানধারক প্রতিস্থাপনটি ব্যবহার করা AndroidManifest.xml। এছাড়া হ্যান্ডলগুলি packageNameSuffixবৈশিষ্ট্যাবলী যাতে আপনি থাকতে পারে debugএবং releaseঅন্য কোন কাস্টম একই ডিভাইসে তৈরী করে যেমন হিসাবে ভাল।

applicationVariants.all { variant ->
    def flavor = variant.productFlavors.get(0)
    def buildType = variant.buildType
    variant.processManifest.doLast {
        println '################# Adding Package Names to Manifest #######################'
        replaceInManifest(variant,
            'PACKAGE_NAME',
            [flavor.packageName, buildType.packageNameSuffix].findAll().join()) // ignores null
    }
}

def replaceInManifest(variant, fromString, toString) {
    def flavor = variant.productFlavors.get(0)
    def buildtype = variant.buildType
    def manifestFile = "$buildDir/manifests/${flavor.name}/${buildtype.name}/AndroidManifest.xml"
    def updatedContent = new File(manifestFile).getText('UTF-8').replaceAll(fromString, toString)
    new File(manifestFile).write(updatedContent, 'UTF-8')
}

আপনি এটি gistদেখতে চান যদি এটি পরে বিকশিত হয় তবে তাও আমার কাছে রয়েছে।

আমি একাধিক সংস্থান এবং এক্সএমএল বিশ্লেষণ পদ্ধতির চেয়ে আরও মার্জিত পদ্ধতির বলে মনে করেছি।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.