diff --git a/.idea/misc.xml b/.idea/misc.xml index 6f32454..f797995 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,6 +1,6 @@ - + diff --git a/app/build.gradle b/app/build.gradle index b25250a..337d30b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -26,14 +26,16 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - implementation 'androidx.appcompat:appcompat:1.0.2' - implementation 'androidx.core:core-ktx:1.0.2' + implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'androidx.core:core-ktx:1.1.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation "io.reactivex.rxjava2:rxjava:2.2.2" implementation "io.reactivex.rxjava2:rxandroid:2.1.0" implementation 'com.jakewharton.rxbinding2:rxbinding:2.2.0' implementation 'com.jakewharton.rxbinding2:rxbinding-appcompat-v7:2.2.0' testImplementation 'junit:junit:4.12' - androidTestImplementation 'androidx.test.ext:junit:1.1.0' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' + androidTestImplementation 'androidx.test.ext:junit:1.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + implementation 'androidx.recyclerview:recyclerview:1.1.0' + implementation 'com.google.android.material:material:1.0.0' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 043bfbb..b5431ae 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -9,7 +9,25 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> - + + + + + + + diff --git a/app/src/main/java/pl/edu/amu/wmi/socialaggregator/MainActivity.kt b/app/src/main/java/pl/edu/amu/wmi/socialaggregator/MainActivity.kt deleted file mode 100644 index 1b0a67a..0000000 --- a/app/src/main/java/pl/edu/amu/wmi/socialaggregator/MainActivity.kt +++ /dev/null @@ -1,12 +0,0 @@ -package pl.edu.amu.wmi.socialaggregator - -import androidx.appcompat.app.AppCompatActivity -import android.os.Bundle - -class MainActivity : AppCompatActivity() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.activity_main) - } -} diff --git a/app/src/main/java/pl/edu/amu/wmi/socialaggregator/activity/AddSocialActivity.kt b/app/src/main/java/pl/edu/amu/wmi/socialaggregator/activity/AddSocialActivity.kt new file mode 100644 index 0000000..36ba7e2 --- /dev/null +++ b/app/src/main/java/pl/edu/amu/wmi/socialaggregator/activity/AddSocialActivity.kt @@ -0,0 +1,56 @@ +package pl.edu.amu.wmi.socialaggregator.activity + +import android.os.Bundle +import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity +import androidx.recyclerview.widget.LinearLayoutManager +import kotlinx.android.synthetic.main.activity_add_social.* +import kotlinx.android.synthetic.main.content_add_social.* +import pl.edu.amu.wmi.socialaggregator.R +import pl.edu.amu.wmi.socialaggregator.utils.SocialPlatformsManager +import pl.edu.amu.wmi.socialaggregator.viewholders.SocialWithImageRecycler + +class AddSocialActivity : AppCompatActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_add_social) + setSupportActionBar(toolbar) + + supportActionBar?.setDisplayHomeAsUpEnabled(true) + + val notLoggedInSocials = SocialPlatformsManager.getNotLoggedIn(this) + val loggedInSocials = SocialPlatformsManager.getLoggedIn(this) + val recyclers = mutableListOf(availableSocialsRecyclerView, addSocialRecyclerView) + + availableSocialsRecyclerView.apply { + layoutManager = LinearLayoutManager(this@AddSocialActivity) + adapter = SocialWithImageRecycler( + loggedInSocials, + R.drawable.ic_remove_circle + ) { + it.logout(context) + loggedInSocials.remove(it) + notLoggedInSocials.add(it) + recyclers.forEach { it.adapter?.notifyDataSetChanged() } + Toast.makeText(context, "Logged out from ${it.getName()}!", Toast.LENGTH_SHORT).show() + } + } + + addSocialRecyclerView.apply { + layoutManager = LinearLayoutManager(this@AddSocialActivity) + adapter = SocialWithImageRecycler( + notLoggedInSocials, + R.drawable.ic_add_circle + ) { + it.login(context) + notLoggedInSocials.remove(it) + loggedInSocials.add(it) + recyclers.forEach { it.adapter?.notifyDataSetChanged() } + Toast.makeText(context, "Logged in to ${it.getName()}!", Toast.LENGTH_SHORT).show() + } + } + + } + +} diff --git a/app/src/main/java/pl/edu/amu/wmi/socialaggregator/activity/MainActivity.kt b/app/src/main/java/pl/edu/amu/wmi/socialaggregator/activity/MainActivity.kt new file mode 100644 index 0000000..12d68da --- /dev/null +++ b/app/src/main/java/pl/edu/amu/wmi/socialaggregator/activity/MainActivity.kt @@ -0,0 +1,53 @@ +package pl.edu.amu.wmi.socialaggregator.activity + +import android.content.Intent +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.recyclerview.widget.LinearLayoutManager +import com.jakewharton.rxbinding2.view.RxView +import io.reactivex.disposables.CompositeDisposable +import kotlinx.android.synthetic.main.activity_main.* +import pl.edu.amu.wmi.socialaggregator.R +import pl.edu.amu.wmi.socialaggregator.utils.SocialPlatformsManager +import pl.edu.amu.wmi.socialaggregator.viewholders.PostTextRecycler +import pl.edu.amu.wmi.socialaggregator.viewholders.SocialWithImageRecycler + +class MainActivity : AppCompatActivity() { + + private val subs = CompositeDisposable() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + + subs.addAll( + RxView.clicks(createPostButton) + .subscribe { + val intent = Intent(this, NewPostActivity::class.java) + startActivity(intent) + }, + RxView.clicks(connectedSocialsButton) + .subscribe { + val intent = Intent(this, AddSocialActivity::class.java) + startActivity(intent) + } + ) + + connectedSocialsRecyclerView.apply { + layoutManager = LinearLayoutManager(this@MainActivity) + adapter = SocialWithImageRecycler(SocialPlatformsManager.getLoggedIn(this@MainActivity), + R.drawable.ic_launcher_background) {} + } + + previousPostsRecyclerView.apply { + layoutManager = LinearLayoutManager(this@MainActivity) + adapter = PostTextRecycler(SocialPlatformsManager.getLoggedIn(this@MainActivity) + .map { it to it.getPosts(this@MainActivity).size }) + } + } + + override fun onDestroy() { + super.onDestroy() + subs.clear() + } +} diff --git a/app/src/main/java/pl/edu/amu/wmi/socialaggregator/activity/NewPostActivity.kt b/app/src/main/java/pl/edu/amu/wmi/socialaggregator/activity/NewPostActivity.kt new file mode 100644 index 0000000..ecb0e0e --- /dev/null +++ b/app/src/main/java/pl/edu/amu/wmi/socialaggregator/activity/NewPostActivity.kt @@ -0,0 +1,51 @@ +package pl.edu.amu.wmi.socialaggregator.activity + +import android.annotation.SuppressLint +import android.os.Bundle +import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity +import androidx.recyclerview.widget.LinearLayoutManager +import com.google.android.material.snackbar.Snackbar +import com.jakewharton.rxbinding2.view.RxView +import kotlinx.android.synthetic.main.activity_new_post.* +import kotlinx.android.synthetic.main.content_new_post.* +import pl.edu.amu.wmi.socialaggregator.R +import pl.edu.amu.wmi.socialaggregator.utils.SocialPlatformsManager +import pl.edu.amu.wmi.socialaggregator.viewholders.SocialWithToggleRecycler + +class NewPostActivity : AppCompatActivity() { + + @SuppressLint("CheckResult") + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_new_post) + setSupportActionBar(toolbar) + + publishPost.setOnClickListener { view -> + Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) + .setAction("Action", null).show() + } + supportActionBar?.setDisplayHomeAsUpEnabled(true) + + val loggedInSocials = SocialPlatformsManager.getLoggedIn(this) + + val availablesRecycler = SocialWithToggleRecycler(loggedInSocials) + availableSocials.apply { + layoutManager = LinearLayoutManager(this@NewPostActivity) + adapter = availablesRecycler + } + + RxView.clicks(publishPost) + .subscribe { + availablesRecycler.chips.entries.forEach { (social, chip) -> + if (chip.isChecked) { + social.addPost(this, postText.text?.toString() ?: "test", emptyList()) + Toast.makeText(this, "Posted to ${social.getName()}!", Toast.LENGTH_LONG) + .show() + } + } + finish() + } + } + +} diff --git a/app/src/main/java/pl/edu/amu/wmi/socialaggregator/socialplatforms/FacebookMock.kt b/app/src/main/java/pl/edu/amu/wmi/socialaggregator/socialplatforms/FacebookMock.kt new file mode 100644 index 0000000..2e3f651 --- /dev/null +++ b/app/src/main/java/pl/edu/amu/wmi/socialaggregator/socialplatforms/FacebookMock.kt @@ -0,0 +1,65 @@ +package pl.edu.amu.wmi.socialaggregator.socialplatforms + +import android.content.Context +import android.graphics.Bitmap +import android.util.Log +import pl.edu.amu.wmi.socialaggregator.utils.InternalStorage +import java.io.ByteArrayOutputStream +import java.io.File + +class FacebookMock : SocialPlatform { + + companion object { + val TAG = FacebookMock::class.java.canonicalName + } + + override fun getName(): String = "Facebook" + + override fun login(context: Context) { + val loginsDir = InternalStorage.getFileOrDir(context, "logins") + if (loginsDir != null) { + val loginFile = File(loginsDir, "facebook") + loginFile.createNewFile() + } else { + Log.e(TAG, "Could not create logins directory") + } + } + + override fun logout(context: Context) { + InternalStorage.getFileOrDir(context, "logins/facebook")?.delete() + } + + override fun isLoggedIn(context: Context): Boolean { + return InternalStorage.getFileOrDir(context, "logins/facebook")?.exists() ?: false + } + + override fun addPost(context: Context, text: String, images: List) { + val postsDir = InternalStorage.getFileOrDir(context, "posts/facebook") + if (postsDir != null) { + val postDir = File(postsDir, System.currentTimeMillis().toString()) + postDir.mkdirs() + + val textFile = File(postDir, "content") + textFile.createNewFile() + textFile.writeText(text) + + images.forEachIndexed { index, image -> + val imageFile = File(postDir, "image$index") + imageFile.createNewFile() + + ByteArrayOutputStream().use { stream -> + image.compress(Bitmap.CompressFormat.JPEG, 100, stream) + imageFile.writeBytes(stream.toByteArray()) + } + } + + } else { + Log.e(TAG, "Could not create posts directory") + } + } + + override fun getPosts(context: Context): List { + val postsDir = InternalStorage.getFileOrDir(context, "posts/facebook") + return postsDir?.listFiles()?.map { it.name }?.toList() ?: emptyList() + } +} \ No newline at end of file diff --git a/app/src/main/java/pl/edu/amu/wmi/socialaggregator/socialplatforms/SocialPlatform.kt b/app/src/main/java/pl/edu/amu/wmi/socialaggregator/socialplatforms/SocialPlatform.kt new file mode 100644 index 0000000..ce822f6 --- /dev/null +++ b/app/src/main/java/pl/edu/amu/wmi/socialaggregator/socialplatforms/SocialPlatform.kt @@ -0,0 +1,14 @@ +package pl.edu.amu.wmi.socialaggregator.socialplatforms + +import android.content.Context +import android.graphics.Bitmap + +interface SocialPlatform { + + fun getName(): String + fun login(context: Context) + fun logout(context: Context) + fun isLoggedIn(context: Context): Boolean + fun addPost(context: Context, text: String, images: List) + fun getPosts(context: Context): List +} \ No newline at end of file diff --git a/app/src/main/java/pl/edu/amu/wmi/socialaggregator/utils/InternalStorage.kt b/app/src/main/java/pl/edu/amu/wmi/socialaggregator/utils/InternalStorage.kt new file mode 100644 index 0000000..1c12a13 --- /dev/null +++ b/app/src/main/java/pl/edu/amu/wmi/socialaggregator/utils/InternalStorage.kt @@ -0,0 +1,25 @@ +package pl.edu.amu.wmi.socialaggregator.utils + +import android.content.Context +import java.io.File + +object InternalStorage { + + fun getFileOrDir(context: Context, name: String): File? { + var file = context.filesDir + + if (name.indexOf("/") > 0) { + val subdirs = name.split("/") + subdirs.subList(0, subdirs.size - 1).forEach { + file = File(file, it) + file.mkdir() + } + file = File(file, subdirs.last()) + } else { + file = File(file, name) + } + + return file + } + +} \ No newline at end of file diff --git a/app/src/main/java/pl/edu/amu/wmi/socialaggregator/utils/SocialPlatformsManager.kt b/app/src/main/java/pl/edu/amu/wmi/socialaggregator/utils/SocialPlatformsManager.kt new file mode 100644 index 0000000..0b656a4 --- /dev/null +++ b/app/src/main/java/pl/edu/amu/wmi/socialaggregator/utils/SocialPlatformsManager.kt @@ -0,0 +1,17 @@ +package pl.edu.amu.wmi.socialaggregator.utils + +import android.content.Context +import pl.edu.amu.wmi.socialaggregator.socialplatforms.FacebookMock +import pl.edu.amu.wmi.socialaggregator.socialplatforms.SocialPlatform + +object SocialPlatformsManager { + private val IMPLEMENTED_PLATFORMS = listOf( + FacebookMock() + ) + + fun getLoggedIn(context: Context) = + IMPLEMENTED_PLATFORMS.filter { it.isLoggedIn(context) }.toMutableList() + + fun getNotLoggedIn(context: Context) = + (IMPLEMENTED_PLATFORMS - getLoggedIn(context)).toMutableList() +} diff --git a/app/src/main/java/pl/edu/amu/wmi/socialaggregator/viewholders/PostTextRecycler.kt b/app/src/main/java/pl/edu/amu/wmi/socialaggregator/viewholders/PostTextRecycler.kt new file mode 100644 index 0000000..8066cab --- /dev/null +++ b/app/src/main/java/pl/edu/amu/wmi/socialaggregator/viewholders/PostTextRecycler.kt @@ -0,0 +1,44 @@ +package pl.edu.amu.wmi.socialaggregator.viewholders + +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.recyclerview.widget.RecyclerView +import com.jakewharton.rxbinding2.view.RxView +import io.reactivex.disposables.Disposable +import pl.edu.amu.wmi.socialaggregator.R +import pl.edu.amu.wmi.socialaggregator.socialplatforms.SocialPlatform + +class PostTextRecycler( + val socials: List>) : RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + val layout = LayoutInflater.from(parent.context) + .inflate(R.layout.previous_posts, parent, false) as ConstraintLayout + + val socialName = layout.findViewById(R.id.socialTextView) + val postCount = layout.findViewById(R.id.postCountTextView) + + return ViewHolder(layout, socialName, postCount) + } + + override fun getItemCount(): Int { + return socials.size + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + val pair = socials[position] + holder.socialName.text = pair.first.getName() + val count = pair.second + holder.postCount.text = count.toString() + if (count > 1) " posts" else " post" + } + + class ViewHolder( + root: ConstraintLayout, + val socialName: TextView, + val postCount: TextView + ) : RecyclerView.ViewHolder(root) + +} \ No newline at end of file diff --git a/app/src/main/java/pl/edu/amu/wmi/socialaggregator/viewholders/SocialWithImageRecycler.kt b/app/src/main/java/pl/edu/amu/wmi/socialaggregator/viewholders/SocialWithImageRecycler.kt new file mode 100644 index 0000000..e500063 --- /dev/null +++ b/app/src/main/java/pl/edu/amu/wmi/socialaggregator/viewholders/SocialWithImageRecycler.kt @@ -0,0 +1,52 @@ +package pl.edu.amu.wmi.socialaggregator.viewholders + +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.recyclerview.widget.RecyclerView +import com.jakewharton.rxbinding2.view.RxView +import io.reactivex.disposables.Disposable +import pl.edu.amu.wmi.socialaggregator.R +import pl.edu.amu.wmi.socialaggregator.socialplatforms.SocialPlatform + +class SocialWithImageRecycler( + val availableSocials: List, + private val imageResource: Int, + private val action: (SocialPlatform) -> Unit +) : RecyclerView.Adapter() { + + private val disposables = HashMap() + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + val layout = LayoutInflater.from(parent.context) + .inflate(R.layout.social_platform_image, parent, false) as ConstraintLayout + + val textView = layout.findViewById(R.id.socialPlatformName) + val imageView = layout.findViewById(R.id.socialPlatformImage) + + return ViewHolder(layout, textView, imageView) + } + + override fun getItemCount(): Int { + return availableSocials.size + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + val social = availableSocials[position] + holder.text.text = social.getName() + holder.image.setImageResource(imageResource) + + disposables[social] = RxView.clicks(holder.image) + .map { social } + .subscribe(action) + } + + class ViewHolder( + root: ConstraintLayout, + val text: TextView, + val image: ImageView + ) : RecyclerView.ViewHolder(root) + +} \ No newline at end of file diff --git a/app/src/main/java/pl/edu/amu/wmi/socialaggregator/viewholders/SocialWithToggleRecycler.kt b/app/src/main/java/pl/edu/amu/wmi/socialaggregator/viewholders/SocialWithToggleRecycler.kt new file mode 100644 index 0000000..3284ded --- /dev/null +++ b/app/src/main/java/pl/edu/amu/wmi/socialaggregator/viewholders/SocialWithToggleRecycler.kt @@ -0,0 +1,46 @@ +package pl.edu.amu.wmi.socialaggregator.viewholders + +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.CheckBox +import android.widget.TextView +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.recyclerview.widget.RecyclerView +import com.google.android.material.chip.Chip +import pl.edu.amu.wmi.socialaggregator.R +import pl.edu.amu.wmi.socialaggregator.socialplatforms.SocialPlatform + +class SocialWithToggleRecycler( + private val availableSocials: List +) : RecyclerView.Adapter() { + + val chips = HashMap() + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + val layout = LayoutInflater.from(parent.context) + .inflate(R.layout.social_platform_toggle, parent, false) as ConstraintLayout + + val textView = layout.findViewById(R.id.socialPlatformName) + val chip = layout.findViewById(R.id.chip) + + return ViewHolder(layout, textView, chip) + } + + override fun getItemCount(): Int { + return availableSocials.size + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + val social = availableSocials[position] + holder.text.text = social.getName() + + chips[social] = holder.chip + } + + class ViewHolder( + root: ConstraintLayout, + val text: TextView, + val chip: CheckBox + ) : RecyclerView.ViewHolder(root) + +} \ No newline at end of file diff --git a/app/src/main/res/drawable-hdpi/ic_add_circle.png b/app/src/main/res/drawable-hdpi/ic_add_circle.png new file mode 100644 index 0000000..4491a34 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_add_circle.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_remove_circle.png b/app/src/main/res/drawable-hdpi/ic_remove_circle.png new file mode 100644 index 0000000..6859a5d Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_remove_circle.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_add_circle.png b/app/src/main/res/drawable-mdpi/ic_add_circle.png new file mode 100644 index 0000000..3f8a548 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_add_circle.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_remove_circle.png b/app/src/main/res/drawable-mdpi/ic_remove_circle.png new file mode 100644 index 0000000..057993f Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_remove_circle.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_add_circle.png b/app/src/main/res/drawable-xhdpi/ic_add_circle.png new file mode 100644 index 0000000..36b842f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_add_circle.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_remove_circle.png b/app/src/main/res/drawable-xhdpi/ic_remove_circle.png new file mode 100644 index 0000000..beb4b3c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_remove_circle.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_add_circle.png b/app/src/main/res/drawable-xxhdpi/ic_add_circle.png new file mode 100644 index 0000000..f32b4ac Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_add_circle.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_remove_circle.png b/app/src/main/res/drawable-xxhdpi/ic_remove_circle.png new file mode 100644 index 0000000..963ee79 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_remove_circle.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_add_circle.png b/app/src/main/res/drawable-xxxhdpi/ic_add_circle.png new file mode 100644 index 0000000..464e907 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_add_circle.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_remove_circle.png b/app/src/main/res/drawable-xxxhdpi/ic_remove_circle.png new file mode 100644 index 0000000..617ddb4 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_remove_circle.png differ diff --git a/app/src/main/res/layout/activity_add_social.xml b/app/src/main/res/layout/activity_add_social.xml new file mode 100644 index 0000000..0073ff6 --- /dev/null +++ b/app/src/main/res/layout/activity_add_social.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index ca0c0de..e51cb25 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -4,15 +4,136 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".MainActivity"> + tools:context=".activity.MainActivity"> - + + + + + + + +