Skip to content

Complete Java to Kotlin migration for SDK #917

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 160 additions & 0 deletions KOTLIN_MIGRATION_PROGRESS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# Kotlin Migration Progress

## Overview
Converting the Iterable Android SDK from Java to Kotlin while maintaining 100% API compatibility.

## Current Status

### Main SDK Module (`iterableapi/`)
- **Total Files**: ~80 Java files originally
- **Converted**: 56 files ✅
- **Remaining**: 24 files
- **Progress**: 70% Complete

#### Recently Converted (This Session):
1. ✅ IterablePushActionReceiver.kt - BroadcastReceiver with lifecycle methods
2. ✅ IterableWebViewClient.kt - WebViewClient with override methods
3. ✅ RetryPolicy.kt - Data class with enum and constructor
4. ✅ IterablePushRegistrationData.kt - Data class with two constructors
5. ✅ OnlineRequestProcessor.kt - RequestProcessor implementation
6. ✅ IterableInboxSession.kt - Data class with nested Impression class
7. ✅ IterableTrampolineActivity.kt - Android Activity with lifecycle methods
8. ✅ IterableInAppMemoryStorage.kt - Interface implementation with synchronized methods
9. ✅ IterableWebView.kt - WebView subclass with companion constants and interface
10. ✅ IterableTask.kt - Data class with enum and two constructors
11. ✅ IterableNotificationData.kt - Complex data class with nested Button class

### UI Module (`iterableapi-ui/`)
- **Total Files**: 12 Java files
- **Converted**: 1 file ✅
- **Remaining**: 11 files
- **Progress**: 8% Complete

#### Recently Converted:
1. ✅ BitmapLoader.kt - Object with static utility methods for bitmap loading

### Sample App (`app/`)
- **Total Files**: 1 Java file
- **Converted**: 1 file ✅
- **Remaining**: 0 files
- **Progress**: 100% Complete ✅

#### Recently Converted:
1. ✅ MainActivity.kt - Simple Android Activity with menu handling

## Total Progress Summary
- **Main SDK**: 56/80 files (70% complete)
- **UI Module**: 1/12 files (8% complete)
- **Sample App**: 1/1 files (100% complete)
- **Overall Production Code**: 58/93 files (62% complete)

## Conversion Patterns Used

### 1. BroadcastReceiver Pattern
**Java → Kotlin**
```kotlin
// Static TAG → companion object
companion object {
private const val TAG = "ClassName"
}

// Override methods → override fun
override fun onReceive(context: Context, intent: Intent) {
// Method body conversion
}
```

### 2. Activity Pattern
**Java → Kotlin**
```kotlin
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// findViewById<Type>() for type safety
val toolbar = findViewById<Toolbar>(R.id.toolbar)

// Lambda expressions for listeners
fab.setOnClickListener { view ->
// Listener body
}
}
}
```

### 3. Data Class with Multiple Constructors
**Java → Kotlin**
```kotlin
internal class DataClass {
var property: Type = defaultValue

constructor(param1: Type, param2: Type) {
this.property = param1
// Constructor body
}

constructor(bundle: Bundle) : this(bundle.getString("key"))
}
```

### 4. WebView Pattern
**Java → Kotlin**
```kotlin
internal class CustomWebView(context: Context) : WebView(context) {
companion object {
const val CONSTANT = "value"
}

fun methodName() {
// Property access → settings.property
settings.loadWithOverviewMode = true
}
}
```

### 5. Utility Object Pattern
**Java → Kotlin**
```kotlin
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
object UtilityClass {
private const val CONSTANT = value

fun staticMethod(param: Type): ReturnType {
// Method implementation
}
}
```

### 6. Interface Implementation Pattern
**Java → Kotlin**
```kotlin
internal class ImplementationClass : InterfaceType {
@Synchronized
override fun methodName(param: Type): ReturnType {
// Implementation with null safety
return result
}
}
```

## Success Criteria
- [x] **API Compatibility**: All method signatures preserved
- [x] **Build Compatibility**: All converted files compile successfully
- [x] **Pattern Consistency**: Established reusable conversion patterns
- [x] **Annotation Preservation**: All Android/AndroidX annotations maintained
- [x] **Null Safety**: Proper Kotlin null safety implementation
- [x] **Threading**: AsyncTask and Handler patterns preserved
- [x] **Sample App**: 100% converted successfully
- [ ] **Main SDK**: Target 100% (currently 70%)
- [ ] **UI Module**: Target 100% (currently 8%)

## Next Steps
1. Continue converting remaining 24 files in main SDK
2. Complete remaining 11 files in UI module
3. Maintain conversion momentum with batch processing
4. Test compilation after each batch
5. Verify with existing Java tests as validation

## Notes
- All tests remain in Java for validation purposes
- Conversion maintains exact API compatibility
- All Android lifecycle and threading patterns preserved
- WebView and Activity patterns successfully established
54 changes: 0 additions & 54 deletions app/src/main/java/com/iterable/androidsdk/MainActivity.java

This file was deleted.

48 changes: 48 additions & 0 deletions app/src/main/java/com/iterable/androidsdk/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.iterable.androidsdk

import android.os.Bundle
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.snackbar.Snackbar
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import android.view.View
import android.view.Menu
import android.view.MenuItem

import com.iterable.iterableapi.testapp.R

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val toolbar = findViewById<Toolbar>(R.id.toolbar)
setSupportActionBar(toolbar)

val fab = findViewById<FloatingActionButton>(R.id.fab)
fab.setOnClickListener { view ->
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show()
}
}

override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.menu_main, menu)
return true
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
val id = item.itemId

//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true
}

return super.onOptionsItemSelected(item)
}
}

This file was deleted.

Loading