Dagger 2 with Instant App - dagger-2

I've been working on instant app for a few days. I didn't get it compiled yet due to Dagger issue.
The project is split into base, export, preview as features.
In export module
#ExportScope
#Component(
modules = [DrawExportModule::class],
dependencies = [AppComponent::class])
interface DrawExportComponent: AndroidInjector<LiveDrawingExportActivity> {
#Component.Builder
abstract class Builder : AndroidInjector.Builder<LiveDrawingExportActivity>(){
abstract fun plus(component: AppComponent): Builder
}
}
AppComponent.kt
#Singleton
#Component(modules = [
AndroidInjectionModule::class,
AppModule::class,
ActivityBindingModule::class,
ServiceBindingModule::class])
interface AppComponent {
#Component.Builder
interface Builder {
#BindsInstance
fun application(context: Context): Builder
fun build(): AppComponent
}
fun inject(app: LiveMessageApplication)
}
AppModule.kt
#Module(includes = [(DataModule::class)])
class AppModule {
#Singleton
#Provides
fun provideStateManager(): StateManager {
return StateManager.getInstance()
}
}
Compile error log
/Users/*/features/export/build/tmp/kapt3/stubs/debug/*/ui/draw/di/DrawExportComponent.java:8:
error: [Dagger/MissingBinding] [dagger.android.AndroidInjector.inject(T)] *.ui.StateManager cannot be provided without an #Inject constructor or an #Provides-annotated method.
public abstract interface DrawExportComponent extends dagger.android.AndroidInjector<com.ctech.livemessage.ui.draw.LiveDrawingExportActivity> {
^
*.ui.StateManager is injected at
*.LiveDrawingExportActivity.stateManager
*.LiveDrawingExportActivity is injected at
dagger.android.AndroidInjector.inject(T)
It seems to me dependency component doesn't work in this case. I have no clue to go forward.
More information
base/build.gradle
apply plugin: 'com.android.feature'
apply plugin: 'io.fabric'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion deps.build.compileSdkVersion
baseFeature = true
defaultConfig {
minSdkVersion deps.build.minSdkVersion
targetSdkVersion deps.build.targetSdkVersion
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.debug
}
}
compileOptions {
sourceCompatibility 1.8
targetCompatibility 1.8
}
}
dependencies {
application project(":installed")
feature project(":features:export")
feature project(":features:preview")
}
export/build.gradle
apply plugin: 'com.android.feature'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion deps.build.compileSdkVersion
defaultConfig {
minSdkVersion deps.build.minSdkVersion
targetSdkVersion deps.build.targetSdkVersion
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
debuggable true
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), '../../proguard.pro'
signingConfig signingConfigs.debug
}
}
sourceSets {
main {
jniLibs.srcDirs 'libs'
}
}
compileOptions {
sourceCompatibility 1.8
targetCompatibility 1.8
}
}
dependencies {
implementation project(':features:base')
kapt deps.dagger.compiler
kapt deps.dagger.androidCompiler
}

The issue is that DrawExportComponent doesn't see StateManager, because the latter is part of AppComponent.
Unlike subcomponents, with component dependencies, dependent components don't get access to all of parent component. You have to explicitly specify what's shared, by adding:
fun stateManager(): StateManager
to your AppComponent.
More info in official documentation

Related

Unable to receive moengage push notifications

I have go through the documentation of moengage flutter but unable to receive the notifications
i have added fcm keys in dashboard also. Below in my implementation
When i am sending notification through fcm are working fine
basically we have 2 modes of flutter apk prod and debug and i am working on debug i have added debug package name in moengage dashboard.
when i create campaign and send a push to android all users its not working. Please help here
Application.kt class
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback
import io.flutter.plugins.GeneratedPluginRegistrant
import com.moengage.core.LogLevel
import com.moengage.core.MoEngage
import com.moengage.core.MoEngage.Builder
import com.moengage.core.config.FcmConfig
import com.moengage.core.config.LogConfig
import com.moengage.core.config.MiPushConfig
import com.moengage.core.config.PushKitConfig
import com.moengage.core.config.NotificationConfig
import com.moengage.flutter.MoEInitializer
import com.moengage.pushbase.MoEPushHelper
import io.flutter.app.FlutterApplication
class Application : FlutterApplication(), PluginRegistrantCallback {
override fun onCreate() {
super.onCreate()
val moEngage = MoEngage.Builder(this, "hereIHaveAddedTheKey")
.build()
MoEngage.initialise(moEngage)
}
override fun registerWith(registry: PluginRegistry?) {
if (registry == null) return
}
}
Build.gradle dependency
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
testImplementation 'junit:junit:4.13.1'
androidTestImplementation 'androidx.test:runner:1.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
implementation 'com.android.support:multidex:1.0.3'
/// ---- moengage sdk start----
implementation("com.moengage:moe-android-sdk:11.2.00")
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation("com.google.firebase:firebase-messaging:20.3.0")
implementation("androidx.lifecycle:lifecycle-process:2.2.0")
implementation("com.moengage:hms-pushkit:2.0.01")
implementation("com.moengage:rich-notification:2.2.00")
implementation("androidx.core:core:1.3.1")
implementation("androidx.appcompat:appcompat:1.2.0")
/// --- end ----
}
app-> build.gradle
buildscript {
ext.kotlin_version = '1.5.21'
repositories {
google()
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.1.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.gms:google-services:4.3.5'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.5.2'
}
}
allprojects {
repositories {
google()
jcenter()
mavenCentral()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}
This is flutter moengage initialization
final MoEngageFlutter _moengagePlugin = MoEngageFlutter();
void initialise() {
_moengagePlugin.initialise();
}
void initState() {
super.initState();
initialise();
}
mainefestFile
<service android:name="com.moengage.firebase.MoEFireBaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
You to add the required metadata for showing push notification and also pass the payload to the SDK using provided API. Refer to the documentation here - https://docs.moengage.com/docs/push-configuration

memory leaks: Empty Android project + Dagger2 + LeakCanary

Faced such a problem.
I create a new project with Empty Activity, and add the dependencies of the project, dagger2 and leakcanary.
Run the application, then close and the leakcanary displays a memory leak.
Add dependencies
android {
compileSdkVersion 26
buildToolsVersion '26.0.3'
defaultConfig {
applicationId "xxxxx"
minSdkVersion 16
targetSdkVersion 26
versionCode 1
versionName "1.0"
}
}
//Dagger
implementation "com.google.dagger:dagger:2.14.1"
kapt "com.google.dagger:dagger-compiler:2.14.1"
//Debug
debugImplementation "com.squareup.leakcanary:leakcanary-android:1.5.4"
Create appkication class and init leakcanary
class AppDelegate: Application() {
override fun onCreate() {
super.onCreate()
onApplicationCreate()
initDagger(this)
}
private fun initDagger(app: Application): AppComponent =
DaggerAppComponent.builder()
.appModule(AppModule(app))
.dataModule(DataModule())
.build()
private fun onApplicationCreate() {
if (BuildConfig.DEBUG) {
if (LeakCanary.isInAnalyzerProcess(this)) {
return
}
LeakCanary.install(this)
}
}
}
MainActivity class
class MainActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
Create dagger component
#Singleton
#Component(modules = arrayOf(AppModule::class, DataModule::class))
interface AppComponent {
}
#Module
class AppModule(private val appContext: Application) {
#Provides
fun provideContext() = appContext
}
#Module
class DataModule {
}
Here is what leakcanary shows screen
If the dependence of the dagger2 is removed, then there is no leakage.
What am I doing wrong?

Spring Boot Gradle setup

I tried to setup gradle in eclipse Luna for a simple spring boot application, but none of the jars are downloaded. Can anyone give me an idea of what I'm missing ?
I ran gradle clean build in the command line and it compiles successfully:
This is the content of my build.gradle file :
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.4.1.RELEASE")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'spring-boot'
jar {
baseName = 'sample'
version = '0.1.0'
}
repositories {
mavenCentral()
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
}
This is the content of the class with the controller:
package sample;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class SampleController {
#RequestMapping("/sample")
public String sampleIt(){
return "Hello! Welcome to Spring Boot Sample. ";
}
}
This is the class with the main function :
package sample;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
#SpringBootApplication
public class SampleApplication {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(SampleApplication.class, args);
System.out.println(ctx.getDisplayName());
System.out.println("This is my first Spring Boot Example");
}
}
Answer from the comment:
It is necessary to install the gradle plugin and import the gradle project afterwards. (Don't forget to click the 'Build Model' button)

fragment inner static class and gradle issues

Initially I was getting an error "This fragment inner class should be static" in the following code:
public class Activity4 extends FragmentActivity {
EditText mEdit;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_activity4);
}
public void selectDate(View view) {
DialogFragment newFragment = new SelectDateFragment();
newFragment.show(getSupportFragmentManager(), "DatePicker");
}
public void populateSetDate(int year, int month, int day) {
mEdit = (EditText) findViewById(R.id.editText);
mEdit.setText(day + "/" + month + "/" + year);
}
//error was here at SelectDateFragment
public class SelectDateFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener {
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Calendar calendar = Calendar.getInstance();
int yy = calendar.get(Calendar.YEAR);
int mm = calendar.get(Calendar.MONTH);
int dd = calendar.get(Calendar.DAY_OF_MONTH);
return new DatePickerDialog(getActivity(), this, yy, mm, dd);
}
public void onDateSet(DatePicker view, int yy, int mm, int dd) {
populateSetDate(yy, mm + 1, dd);
}
}
}
I tried to figure out the solution & read on some post here that its a lint error and can be resolved by adding this to the gradle file:
lintOptions {
abortOnError false
}
but when I did that, I get the message that "cannot resolve symbol getDefaultProguardFile". This is my gradle file:
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultConfig {
applicationId "com.sample.pat1"
minSdkVersion 16
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
lintOptions {
abortOnError false
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.2.0'
}
And the previous error "This fragment inner class should be static" still persists. Surprisingly the app works just fine despite all this.. but I would like to know where I'm going wrong.. Please help!
If you don't want to rewrite the communication mechanic, you can mark fragment as a valid manually:
#SuppressLint("ValidFragment")
DialogFragment newFragment = new SelectDateFragment();
More description here
P.S. Proguard - it's totally another issue.

How to iterate gradle dependencies in custom gradle plugin?

I have followed this guide:
http://www.gradle.org/docs/current/userguide/custom_plugins.html
to create a standalone gradle plugin with the following structure/files:
my-gradle-plugin
> src
> main
> java
> com
> mygroup
> MyGradlePlugin.groovy
> build.gradle
> settings.gradle
build.gradle :
apply plugin: 'groovy'
dependencies {
compile gradleApi()
groovy localGroovy()
}
apply plugin: 'maven'
repositories {
mavenCentral()
}
group = 'com.mygroup'
version = '1.0.0-SNAPSHOT'
MyGradlePlugin.groovy :
package com.mygroup
import org.gradle.api.*
class MyGradlePlugin implements Plugin<Project> {
void apply(Project project) {
print " project.name " + project.name + "\n"
print " project.dependencies " + project.dependencies + "\n"
// How do we iterate each dependency and print artifactId, group, version??
// project.dependencies.each {
// compile(it) {
// print it.next()
// print it.name
// }
// }
project.configurations.each {
print it.dump()
}
}
}
In another project I use/apply this plugin:
apply plugin: 'java'
apply plugin: 'maven'
apply plugin: 'eclipse'
repositories {
mavenLocal()
}
buildscript {
repositories {
mavenLocal()
}
dependencies {
classpath group: 'com.mygroup', name: 'my-gradle-plugin', version: '1.0.0-SNAPSHOT'
}
}
dependencies {
compile group: 'commons-codec', name: 'commons-codec', version: '1.4'
compile group: 'commons-beanutils', name: 'commons-beanutils', version: '1.7.0'
}
install.doLast {
apply plugin: 'my-gradle-plugin'
}
But how do I iterate the commons dependencies from the apply method in MyGradlePlugin.groovy and print their coordinates (artifactId, groupId, version)?
I know this is an old question but since there is not a selected answer I'll throw in an example that I have used. This is based on the example in section 49.8.2.2 of the gradle docs.
I'm using it to do custom dependency resolution, but you can do whatever you'd like inside the dependency iteration. Note that this works because its passing a closure that is executed after the configuration phase.
Plugin code:
package com.overtherainbow
import org.gradle.api.Project
import org.gradle.api.Plugin
import org.gradle.api.artifacts.DependencyResolveDetails
class DefaultVersionPlugin implements Plugin<Project> {
// This is where dependency versions are defined
def defaultVersionsMap = [
'javax.servlet:servlet-api' : '2.5',
'log4j:log4j' : '1.2.16']
void apply(Project project) {
project.configurations.all {
resolutionStrategy.eachDependency {
DependencyResolveDetails details -> resolveDependencyVersion(project, details)
}
}
}
def resolveDependencyVersion(Project project, DependencyResolveDetails details) {
if (details.requested.version == 'default') {
def version = resolveDefaultVersion(project, details.requested.group, details.requested.name)
details.useVersion version
}
}
def resolveDefaultVersion(Project project, String group, String name) {
project.logger.debug("Resolving default dependency for $group:$name")
println "Resolving default dependency for $group:$name"
defaultVersionsMap["$group:$name"]
}
}
The problem is that dependency graph is only available after project is fully evaluated. That's why you can't rely on that directly in the apply method. You have to postpone the execution using the afterEvaluate method. The following code will do the trick:
class MyGradlePlugin implements Plugin<Project> {
void apply(Project project) {
project.afterEvaluate {
println " Project:" + project.name
project.configurations.each { conf ->
println " Configuration: ${conf.name}"
conf.allDependencies.each { dep ->
println " ${dep.group}:${dep.name}:${dep.version}"
}
}
}
}
}
UPDATE: Following question updates and discussions in the comments and chat you can also do the following:
class MyGradlePlugin implements Plugin<Project> {
void apply(Project project) {
project.tasks.findByName('install')?.doLast {
...
}
}
}