0

We do have 2 similar projects for an app. The first one is for my country and the second one is for the EU. They are %90 same may be more. We do want to merge these two projects into one and switch between them with build variants. Is that possible? If it is, how can I do it?

Main Project

@OnClick(R.id.image_view)
    public void onClicked(View view) {
        if (isXEnabled) {
            ImageView.setImageResource(R.drawable.inactive);
            ImageView.setContentDescription(getString(R.string.passive));
            presenter.sendCommand();
            isEnabled = false;
        } else {
            ImageView.setImageResource(R.drawable.active);
            ImageView.setContentDescription(getString(R.string.active));
            presenter.disableFeature();
            isEnabled = true;
        }
    }

EU Project

@OnClick(R.id.image_view)
    public void onClicked(View view) {
        if (isXEnabled) {
            ImageView.setImageResource(R.drawable.EuInactive);
            ImageView.setContentDescription(getString(R.string.EUpassive));
            presenter.sendCommand();
            isEnabled = false;
        } else {
            ImageView.setImageResource(R.drawable.active);
            ImageView.setContentDescription(getString(R.string.EUactive));
            presenter.disableFeature();
            isEnabled = true;
        }
    }

For example, some drawable is different on EU Project

- Or -

Main Project

@OnClick(R.id.image_view)
    public void onClicked(View view) {
        if (isXEnabled) {
            ImageView.setImageResource(R.drawable.inactive);
            ImageView.setContentDescription(getString(R.string.passive));
            presenter.sendCommand();
            isEnabled = false;
            DoSomething();
        } else {
            ImageView.setImageResource(R.drawable.active);
            ImageView.setContentDescription(getString(R.string.active));
            presenter.disableFeature();
            isEnabled = true;
        }
    }

Eu Project

@OnClick(R.id.image_view)
    public void onClicked(View view) {
        if (isXEnabled) {
            ImageView.setImageResource(R.drawable.inactive);
            ImageView.setContentDescription(getString(R.string.passive));
            presenter.sendCommand();
            isEnabled = false;
            DoSomethingElse();
        } else {
            ImageView.setImageResource(R.drawable.active);
            ImageView.setContentDescription(getString(R.string.active));
            presenter.disableFeature();
            isEnabled = true;
        }
    }

In this example we did added different line everything else is similar.

There nearly a thousand of this kind of differences and nearly five hundreds of exactly same classes and two hundreds of new classes.

In conclusion, how can I manage these two projects with build variants in one project?

Edit 2 : I've tried these steps.

  1. Implement dimensions
  2. Implement flavor
  3. Created res,asset,java files for eu project
  4. Created sourceSet in gradle for eu project

for now build variant looks like this mainDevDebug,EuDevDebug,... etc main...... ones works fine but i had an error for Eu..... ones

Error message while rebuilding or running app:

Could not determine the dependencies of task ':app:compileEuTestDebugJavaWithJavac'.
> Could not resolve all task dependencies for configuration ':app:EuTestDebugCompileClasspath'.
   > Could not resolve project :com.xx.core.main.core.
     Required by:
         project :app
      > No matching configuration of project :com.xx.core.main.core was found. The consumer was configured to find an API of a component, as well as attribute 'com.android.build.api.attributes.BuildTypeAttr' with value 'debug', attribute 'project' with value 'Eu', attribute 'default' with value 'Test', attribute 'org.jetbrains.kotlin.platform.type' with value 'androidJvm' but:
          - None of the consumable configurations have attributes.
Nimantha
  • 6,405
  • 6
  • 28
  • 69
  • `We do want to merge this two project into one and switch between them with build variants. Is that possible ?` what have you tried ? – a_local_nobody Jan 07 '21 at 08:47
  • My boss told me to learn how to do it and if you can do it. I've added flavours, buildconfigs etc. but never tried something like that before. Honestly Idk what should i look for on internet because of that I've open this question. Firstly I want to do a research after that I can ask yok guys proper questions. Currently I'm working on differences of 2 projects to understand well. – fatihberatcan Jan 07 '21 at 08:54
  • your question is too broad to ask/answer here, because it really depends on the project and asking `how can i do it` is also a bit broad, but as my personal suggestion, i'd tell you to make a small proof of concept project where you try this out, you'd have to look at [product flavors](https://developer.android.com/studio/build/build-variants) – a_local_nobody Jan 07 '21 at 09:55
  • I understand that but as you know i can't share much detail about my company's project. I've thought about product flavors but I've already added test-dev-prod flavours and debug and release configs. Now it's like DevDebug,ProdRelease on buildconfigs. Now i need to that as xEuDevRelease, xDevRelease etc. Simply another layer but a few classes are missing. For example can i move a few classes to src folder for xEu ? @a_local_nobody – fatihberatcan Jan 07 '21 at 10:09
  • `i can't share much detail about my company's project` the fact that it is a company project should be irrelevant, you should be able to create a [Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example) both here on SO as well as IRL – a_local_nobody Jan 07 '21 at 10:12
  • @a_local_nobody I've added some explaination. What do you think about it ? Could i explain myself ? – fatihberatcan Jan 07 '21 at 11:46
  • yep, your question is starting to show some merit now :) by the looks of it, it seems like the only difference would be strings and image resources ? – a_local_nobody Jan 07 '21 at 11:58
  • i think something [like this](https://sgkantamani.medium.com/android-product-flavors-eb526e35f9f1) should get you started (please note, that's just a random tutorial i find on actually using product flavors, might not be the best article, or, it might be) – a_local_nobody Jan 07 '21 at 12:03
  • %90 of it these kind of things but %10 of it is new implementations. If i be more spesific, that app manages my company's devices we do have a few different devices for eu and our country, that causes the difference. I've used meld to see different modified class count when i click randomly most of it actually import difference, string difference or drawable difference – fatihberatcan Jan 07 '21 at 12:04
  • i'll try to write you up an answer soon, unfortunately (for me) it will have to be quite a lengthy one and probably won't include answers to everything you're looking for, but i'll try my best :) – a_local_nobody Jan 07 '21 at 12:10
  • Thank you very much :) Anything would be helpful to start and I need to learn as well,can't expect everything from someone else – fatihberatcan Jan 07 '21 at 12:14
  • i'll have to get back to you with this, i'll try write an answer later today – a_local_nobody Jan 07 '21 at 12:44
  • have a look at my answer, hopefully it'll help you get started, bit of a rushed answer so hope it works out OK – a_local_nobody Jan 07 '21 at 14:02

1 Answers1

0

From the code you've posted and from the comments, I believe you'd be able to achieve what you're looking for with product flavors read more here.

in your APP-level build.gradle, you'd do something like this :

android {  
    flavorDimensions 'default'
    productFlavors {

        foo{
            dimension 'default'
        }

        bar{
            dimension 'default'
        }

    }
}

this will define two different product flavors for you, specifically foo and bar. after doing a gradle sync, you'll see you now have these available as build variants.

enter image description here

next what you'll do, is create a folder structure similar to this: enter image description here

creating a folder for bar, a folder for foo and leaving the folder for main, with the package signature inside each folder matching what your main structure is using. if you have image resources which will be different, make sure they're in appropriate folders here. If you're struggling to create a specific type of file/folder, I'd suggest just copying it over.

everything inside main will be used in BOTH types of apps, so all the logic which is the same, will remain there. everything which can be different will reside in the folders for bar and for foo. In my case, a simple class called Example:

class Example {

    fun giveValue(context: Context): String {
        return context.getString(R.string.value)
    }
}

the implementation for both of these classes are exactly the same in both folders, although yours could (and will) be entirely different.

You'll also see I have added strings.xml into my product flavors (in your case, perhaps this would be image resources as well), I've added the following string:

<resources>
    <string name="value">from bar</string>
</resources>

into the strings.xml found under the bar directory and

<resources>
    <string name="value">from foo</string>
</resources>

into the strings.xml found under the foo directory

my Example class therefore just returns whatever this value is based on the build variant

and that's it.

inside my main activity:

  val result = Example().giveValue(this)
        Log.v("testing", result) 

so, depending on the build variant i'm using (either fooDebug or barDebug) the output will be different.

a_local_nobody
  • 7,947
  • 5
  • 29
  • 51
  • thank you for your reply. I've built something similar but I've got an error for eu flavor. could you say something about it ? And a second question should i leave only mainactivity and empty folders for main ? because all of them will be different but I've getting an error like "Edit 2". I think if i somehow solve it. It will be done !! Finally thanks again for your help. – fatihberatcan Jan 07 '21 at 14:35
  • if your project doesn't need a main activity there's no point in keeping it, you can remove it, same with everything else you don't need. regarding the error you got, not sure why you're getting that, perhaps something is wrong with the way you've configured your build variants – a_local_nobody Jan 07 '21 at 18:30