From b8e6a04e7c31d4bd8962050028810b68515eaefb Mon Sep 17 00:00:00 2001
From: AdityaVSM
Date: Wed, 28 Apr 2021 22:38:39 +0530
Subject: [PATCH] Added snapchat clone
---
android_apps/SnapChatClone/.gitignore | 15 ++
android_apps/SnapChatClone/README.md | 46 +++++
android_apps/SnapChatClone/app/.gitignore | 1 +
android_apps/SnapChatClone/app/build.gradle | 53 ++++++
.../SnapChatClone/app/google-services.json | 39 ++++
.../SnapChatClone/app/proguard-rules.pro | 21 +++
.../snapchatclone/ExampleInstrumentedTest.kt | 24 +++
.../app/src/main/AndroidManifest.xml | 28 +++
.../snapchatclone/ChoseUserActivity.kt | 57 ++++++
.../snapchatclone/CreateSnapActivity.kt | 108 +++++++++++
.../com/example/snapchatclone/MainActivity.kt | 62 +++++++
.../example/snapchatclone/SnapsActivity.kt | 93 ++++++++++
.../example/snapchatclone/ViewSnapActivity.kt | 70 +++++++
.../drawable-v24/ic_launcher_foreground.xml | 30 +++
.../res/drawable/ic_launcher_background.xml | 170 +++++++++++++++++
.../main/res/layout/activity_chose_user.xml | 21 +++
.../main/res/layout/activity_create_snap.xml | 56 ++++++
.../app/src/main/res/layout/activity_main.xml | 57 ++++++
.../src/main/res/layout/activity_new_snap.xml | 36 ++++
.../src/main/res/layout/activity_snaps.xml | 21 +++
.../app/src/main/res/menu/snaps.xml | 10 +
.../res/mipmap-anydpi-v26/ic_launcher.xml | 5 +
.../mipmap-anydpi-v26/ic_launcher_round.xml | 5 +
.../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 3593 bytes
.../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 5339 bytes
.../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2636 bytes
.../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 3388 bytes
.../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4926 bytes
.../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 7472 bytes
.../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 7909 bytes
.../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 11873 bytes
.../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 10652 bytes
.../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 16570 bytes
.../app/src/main/res/values-night/themes.xml | 16 ++
.../app/src/main/res/values/colors.xml | 10 +
.../app/src/main/res/values/strings.xml | 3 +
.../app/src/main/res/values/themes.xml | 16 ++
.../example/snapchatclone/ExampleUnitTest.kt | 17 ++
android_apps/SnapChatClone/build.gradle | 28 +++
android_apps/SnapChatClone/gradle.properties | 21 +++
.../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54329 bytes
.../gradle/wrapper/gradle-wrapper.properties | 6 +
android_apps/SnapChatClone/gradlew | 172 ++++++++++++++++++
android_apps/SnapChatClone/gradlew.bat | 84 +++++++++
android_apps/SnapChatClone/settings.gradle | 2 +
45 files changed, 1403 insertions(+)
create mode 100644 android_apps/SnapChatClone/.gitignore
create mode 100644 android_apps/SnapChatClone/README.md
create mode 100644 android_apps/SnapChatClone/app/.gitignore
create mode 100644 android_apps/SnapChatClone/app/build.gradle
create mode 100644 android_apps/SnapChatClone/app/google-services.json
create mode 100644 android_apps/SnapChatClone/app/proguard-rules.pro
create mode 100644 android_apps/SnapChatClone/app/src/androidTest/java/com/example/snapchatclone/ExampleInstrumentedTest.kt
create mode 100644 android_apps/SnapChatClone/app/src/main/AndroidManifest.xml
create mode 100644 android_apps/SnapChatClone/app/src/main/java/com/example/snapchatclone/ChoseUserActivity.kt
create mode 100644 android_apps/SnapChatClone/app/src/main/java/com/example/snapchatclone/CreateSnapActivity.kt
create mode 100644 android_apps/SnapChatClone/app/src/main/java/com/example/snapchatclone/MainActivity.kt
create mode 100644 android_apps/SnapChatClone/app/src/main/java/com/example/snapchatclone/SnapsActivity.kt
create mode 100644 android_apps/SnapChatClone/app/src/main/java/com/example/snapchatclone/ViewSnapActivity.kt
create mode 100644 android_apps/SnapChatClone/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
create mode 100644 android_apps/SnapChatClone/app/src/main/res/drawable/ic_launcher_background.xml
create mode 100644 android_apps/SnapChatClone/app/src/main/res/layout/activity_chose_user.xml
create mode 100644 android_apps/SnapChatClone/app/src/main/res/layout/activity_create_snap.xml
create mode 100644 android_apps/SnapChatClone/app/src/main/res/layout/activity_main.xml
create mode 100644 android_apps/SnapChatClone/app/src/main/res/layout/activity_new_snap.xml
create mode 100644 android_apps/SnapChatClone/app/src/main/res/layout/activity_snaps.xml
create mode 100644 android_apps/SnapChatClone/app/src/main/res/menu/snaps.xml
create mode 100644 android_apps/SnapChatClone/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
create mode 100644 android_apps/SnapChatClone/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
create mode 100644 android_apps/SnapChatClone/app/src/main/res/mipmap-hdpi/ic_launcher.png
create mode 100644 android_apps/SnapChatClone/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
create mode 100644 android_apps/SnapChatClone/app/src/main/res/mipmap-mdpi/ic_launcher.png
create mode 100644 android_apps/SnapChatClone/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
create mode 100644 android_apps/SnapChatClone/app/src/main/res/mipmap-xhdpi/ic_launcher.png
create mode 100644 android_apps/SnapChatClone/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
create mode 100644 android_apps/SnapChatClone/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
create mode 100644 android_apps/SnapChatClone/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
create mode 100644 android_apps/SnapChatClone/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
create mode 100644 android_apps/SnapChatClone/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
create mode 100644 android_apps/SnapChatClone/app/src/main/res/values-night/themes.xml
create mode 100644 android_apps/SnapChatClone/app/src/main/res/values/colors.xml
create mode 100644 android_apps/SnapChatClone/app/src/main/res/values/strings.xml
create mode 100644 android_apps/SnapChatClone/app/src/main/res/values/themes.xml
create mode 100644 android_apps/SnapChatClone/app/src/test/java/com/example/snapchatclone/ExampleUnitTest.kt
create mode 100644 android_apps/SnapChatClone/build.gradle
create mode 100644 android_apps/SnapChatClone/gradle.properties
create mode 100644 android_apps/SnapChatClone/gradle/wrapper/gradle-wrapper.jar
create mode 100644 android_apps/SnapChatClone/gradle/wrapper/gradle-wrapper.properties
create mode 100644 android_apps/SnapChatClone/gradlew
create mode 100644 android_apps/SnapChatClone/gradlew.bat
create mode 100644 android_apps/SnapChatClone/settings.gradle
diff --git a/android_apps/SnapChatClone/.gitignore b/android_apps/SnapChatClone/.gitignore
new file mode 100644
index 000000000..aa724b770
--- /dev/null
+++ b/android_apps/SnapChatClone/.gitignore
@@ -0,0 +1,15 @@
+*.iml
+.gradle
+/local.properties
+/.idea/caches
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+/.idea/navEditor.xml
+/.idea/assetWizardSettings.xml
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+.cxx
+local.properties
diff --git a/android_apps/SnapChatClone/README.md b/android_apps/SnapChatClone/README.md
new file mode 100644
index 000000000..eee527513
--- /dev/null
+++ b/android_apps/SnapChatClone/README.md
@@ -0,0 +1,46 @@
+
SnapChat Clone
+
+
+
+
Simple Snapchat like app
+
+
+
+ ### :zap: Features:
+ - [x] Create User account
+ - [x] Send snaps(Choose from Device storage)
+ - [x] Send small message along with snap
+ - [x] View Snap
+ - [x] Automatically delete snap after view
+
+
+
+ ### :sunny: Recomended updates:
+ - [ ] Good UI
+ - [ ] Increase upload speed of images
+
+
+
+ ### 🛠️ Tools Used:
+ 
+ 
+ 
+
+
+
+ ### :confused: How to use:
+
+
+ 1. Download android studio (v3 or higer recomended)
+ 2. Clone the repository using github CLI
+
+ ` gh repo clone AdityaVSM/SnapChatClone `
+
+ 3.Setup Firebase Project. Read official documentation to know more about setting up a project in firebase here
+ 4.Enjoy using the app :blush:
+
+
+ Feel free to contribute:computer:
+
+ ### Thank you:smile:, Happy coding :muscle:
+
diff --git a/android_apps/SnapChatClone/app/.gitignore b/android_apps/SnapChatClone/app/.gitignore
new file mode 100644
index 000000000..42afabfd2
--- /dev/null
+++ b/android_apps/SnapChatClone/app/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/android_apps/SnapChatClone/app/build.gradle b/android_apps/SnapChatClone/app/build.gradle
new file mode 100644
index 000000000..f4418db18
--- /dev/null
+++ b/android_apps/SnapChatClone/app/build.gradle
@@ -0,0 +1,53 @@
+plugins {
+ id 'com.android.application'
+ id 'kotlin-android'
+}
+
+android {
+ compileSdkVersion 30
+ buildToolsVersion "30.0.2"
+
+ defaultConfig {
+ applicationId "com.example.snapchatclone"
+ minSdkVersion 26
+ targetSdkVersion 30
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+}
+
+dependencies {
+
+ implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
+ implementation 'androidx.core:core-ktx:1.3.2'
+ implementation 'androidx.appcompat:appcompat:1.2.0'
+ implementation 'com.google.android.material:material:1.3.0'
+ implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
+ testImplementation 'junit:junit:4.+'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.2'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
+ implementation platform('com.google.firebase:firebase-bom:27.1.0')
+ implementation 'com.google.firebase:firebase-auth-ktx:20.0.4'
+ implementation 'com.google.firebase:firebase-storage-ktx'
+ implementation 'com.google.firebase:firebase-database-ktx'
+
+ implementation 'com.github.bumptech.glide:glide:4.12.0'
+ annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
+}
+apply plugin: 'com.google.gms.google-services'
diff --git a/android_apps/SnapChatClone/app/google-services.json b/android_apps/SnapChatClone/app/google-services.json
new file mode 100644
index 000000000..bbf358937
--- /dev/null
+++ b/android_apps/SnapChatClone/app/google-services.json
@@ -0,0 +1,39 @@
+{
+ "project_info": {
+ "project_number": "867489977492",
+ "project_id": "snapchat-e191b",
+ "storage_bucket": "snapchat-e191b.appspot.com"
+ },
+ "client": [
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:867489977492:android:cacf17a8c841d166699081",
+ "android_client_info": {
+ "package_name": "com.example.snapchatclone"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "867489977492-94j0iho548618oh7qiuk98qr4u4t98jd.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyBtsCEMkXJbnN56MdwbPYmreylQ6EG5Fkk"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "867489977492-94j0iho548618oh7qiuk98qr4u4t98jd.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "configuration_version": "1"
+}
\ No newline at end of file
diff --git a/android_apps/SnapChatClone/app/proguard-rules.pro b/android_apps/SnapChatClone/app/proguard-rules.pro
new file mode 100644
index 000000000..481bb4348
--- /dev/null
+++ b/android_apps/SnapChatClone/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/android_apps/SnapChatClone/app/src/androidTest/java/com/example/snapchatclone/ExampleInstrumentedTest.kt b/android_apps/SnapChatClone/app/src/androidTest/java/com/example/snapchatclone/ExampleInstrumentedTest.kt
new file mode 100644
index 000000000..30f6162b6
--- /dev/null
+++ b/android_apps/SnapChatClone/app/src/androidTest/java/com/example/snapchatclone/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package com.example.snapchatclone
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+ assertEquals("com.example.snapchatclone", appContext.packageName)
+ }
+}
\ No newline at end of file
diff --git a/android_apps/SnapChatClone/app/src/main/AndroidManifest.xml b/android_apps/SnapChatClone/app/src/main/AndroidManifest.xml
new file mode 100644
index 000000000..ea2273655
--- /dev/null
+++ b/android_apps/SnapChatClone/app/src/main/AndroidManifest.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android_apps/SnapChatClone/app/src/main/java/com/example/snapchatclone/ChoseUserActivity.kt b/android_apps/SnapChatClone/app/src/main/java/com/example/snapchatclone/ChoseUserActivity.kt
new file mode 100644
index 000000000..31dd7890f
--- /dev/null
+++ b/android_apps/SnapChatClone/app/src/main/java/com/example/snapchatclone/ChoseUserActivity.kt
@@ -0,0 +1,57 @@
+package com.example.snapchatclone
+
+import android.content.Intent
+import androidx.appcompat.app.AppCompatActivity
+import android.os.Bundle
+import android.util.Log
+import android.widget.AdapterView
+import android.widget.ArrayAdapter
+import android.widget.ListView
+import com.google.firebase.FirebaseError
+import com.google.firebase.auth.FirebaseAuth
+import com.google.firebase.database.*
+import com.google.firebase.ktx.Firebase
+
+class ChoseUserActivity : AppCompatActivity() {
+ var chooseUserListView: ListView? = null
+ var emailsArrayList:ArrayList = ArrayList()
+ var userNameArrayList:ArrayList = ArrayList()
+ var keys:ArrayList = ArrayList()
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_chose_user)
+
+ chooseUserListView = findViewById(R.id.chooseUserListView)
+ val arrayAdapter = ArrayAdapter(this,android.R.layout.simple_list_item_1,userNameArrayList)
+ chooseUserListView?.adapter = arrayAdapter
+
+ var userName = "";
+ FirebaseDatabase.getInstance().getReference().child("users").addChildEventListener(object :ChildEventListener {
+ override fun onChildAdded(snapshot: DataSnapshot, previousChildName: String?) {
+ userName = snapshot?.child("userName")?.value as String
+ userNameArrayList.add(userName)
+ keys.add(snapshot.key.toString())
+ arrayAdapter.notifyDataSetChanged()
+ }
+
+ override fun onChildChanged(snapshot: DataSnapshot, previousChildName: String?) {}
+ override fun onChildRemoved(snapshot: DataSnapshot) {}
+ override fun onChildMoved(snapshot: DataSnapshot, previousChildName: String?) {}
+ override fun onCancelled(error: DatabaseError) {}
+ })
+ chooseUserListView?.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id ->
+ val snapMap: Any = mapOf("from" to userName, "imageName" to intent.getStringExtra("imageName"), "imageUrl" to intent.getStringExtra("imageUrl"), "message" to intent.getStringExtra("message")) as Any
+ FirebaseDatabase.getInstance().getReference().child("users").child(keys.get(position)).child("snaps").push().setValue(snapMap)
+
+ val intent = Intent(this,SnapsActivity::class.java)
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+ startActivity(intent)
+ }
+
+ }
+
+
+
+}
+
diff --git a/android_apps/SnapChatClone/app/src/main/java/com/example/snapchatclone/CreateSnapActivity.kt b/android_apps/SnapChatClone/app/src/main/java/com/example/snapchatclone/CreateSnapActivity.kt
new file mode 100644
index 000000000..0187a80f7
--- /dev/null
+++ b/android_apps/SnapChatClone/app/src/main/java/com/example/snapchatclone/CreateSnapActivity.kt
@@ -0,0 +1,108 @@
+package com.example.snapchatclone
+
+import android.app.Activity
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.graphics.Bitmap
+import android.graphics.drawable.BitmapDrawable
+import android.net.Uri
+import android.os.Bundle
+import android.provider.MediaStore
+import android.util.Log
+import android.view.View
+import android.widget.EditText
+import android.widget.ImageView
+import android.widget.Toast
+import androidx.appcompat.app.AppCompatActivity
+import com.google.android.gms.tasks.Task
+import com.google.firebase.storage.FirebaseStorage
+import java.io.ByteArrayOutputStream
+import java.util.*
+
+
+class CreateSnapActivity : AppCompatActivity() {
+
+ var createSnapImageView:ImageView? = null
+ var messageEditText:EditText? = null
+ val imageName = UUID.randomUUID().toString()+ ".jpg";
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_create_snap)
+
+ createSnapImageView = findViewById(R.id.createSnapImageView)
+ messageEditText = findViewById(R.id.messageEditText)
+ }
+
+ fun getPhoto(){
+ val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
+ startActivityForResult(intent, 1)
+ }
+
+ fun chooseImage(view: View){
+ if(checkSelfPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
+ requestPermissions(arrayOf(android.Manifest.permission.READ_EXTERNAL_STORAGE), 1)
+ }else{
+ getPhoto()
+ }
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ super.onActivityResult(requestCode, resultCode, data)
+ val selectedImage = data!!.data
+
+ if(requestCode == 1 && resultCode == Activity.RESULT_OK && data != null){
+ try{
+ val bitmap = MediaStore.Images.Media.getBitmap(this.contentResolver, selectedImage)
+ createSnapImageView?.setImageBitmap(bitmap)
+ }catch (e: Exception){
+ e.printStackTrace()
+ }
+ }
+ }
+
+ override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
+ if(requestCode == 1){
+ if(grantResults.size > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
+ getPhoto()
+ }
+ }
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+ }
+
+ fun nextClicked(view: View){
+ createSnapImageView?.isDrawingCacheEnabled = true
+ createSnapImageView?.buildDrawingCache()
+ val bitmap = (createSnapImageView?.drawable as BitmapDrawable).bitmap
+ val baos = ByteArrayOutputStream()
+ bitmap?.compress(Bitmap.CompressFormat.JPEG, 100, baos)
+ val data = baos.toByteArray()
+
+ //FirebaseStorage.getInstance().getReference().child("Images").child(imageName)
+
+ var uploadTask = FirebaseStorage.getInstance().getReference().child("Images").child(imageName).putBytes(data)
+ uploadTask.addOnSuccessListener { taskSnapshot ->
+ if (taskSnapshot.metadata != null) {
+ if (taskSnapshot.metadata!!.reference != null) {
+ val result: Task = taskSnapshot.storage.downloadUrl
+ result.addOnSuccessListener { uri ->
+ val imageUrl: String = uri.toString()
+ Log.i("Download url : ", imageUrl.toString())
+
+ val intent = Intent(this, ChoseUserActivity::class.java)
+ intent.putExtra("imageUrl", imageUrl)
+ intent.putExtra("imageName", imageName)
+ intent.putExtra("message", messageEditText?.text.toString())
+ startActivity(intent)
+ }
+ }
+ }
+ }.addOnFailureListener {
+ // Handle unsuccessful uploads
+ Toast.makeText(this, "Upload failed", Toast.LENGTH_SHORT).show()
+ }
+
+
+
+ }
+}
\ No newline at end of file
diff --git a/android_apps/SnapChatClone/app/src/main/java/com/example/snapchatclone/MainActivity.kt b/android_apps/SnapChatClone/app/src/main/java/com/example/snapchatclone/MainActivity.kt
new file mode 100644
index 000000000..4c207e116
--- /dev/null
+++ b/android_apps/SnapChatClone/app/src/main/java/com/example/snapchatclone/MainActivity.kt
@@ -0,0 +1,62 @@
+package com.example.snapchatclone
+
+import android.content.Intent
+import androidx.appcompat.app.AppCompatActivity
+import android.os.Bundle
+import android.util.Log
+import android.view.View
+import android.widget.EditText
+import android.widget.Toast
+import com.google.firebase.auth.FirebaseAuth
+import com.google.firebase.database.FirebaseDatabase
+import com.google.firebase.ktx.Firebase
+
+class MainActivity : AppCompatActivity() {
+ var userNameEditText:EditText?=null
+ var emailEditText : EditText?=null
+ var passwordEditText : EditText?=null
+ val mAuth = FirebaseAuth.getInstance()
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main)
+
+ userNameEditText = findViewById(R.id.userNameEditText)
+ emailEditText = findViewById(R.id.emailEditText);
+ passwordEditText = findViewById(R.id.passwordEditText)
+
+ if(mAuth.currentUser != null){
+ login()
+ }
+ }
+
+ fun goClicked(view: View){
+ //Check if we can login the user
+
+ mAuth.signInWithEmailAndPassword(emailEditText?.text.toString(), passwordEditText?.text.toString())
+ .addOnCompleteListener(this) { task ->
+ if (task.isSuccessful) {
+ login();
+ } else {
+ // Sign up user
+ mAuth.createUserWithEmailAndPassword(emailEditText?.text.toString(), passwordEditText?.text.toString())
+ .addOnCompleteListener(this) { task ->
+ if(task.isSuccessful){
+ //Add to database
+ FirebaseDatabase.getInstance().getReference().child("users").child(task.result!!.user?.uid!!).child("email").setValue(emailEditText?.text.toString())
+ FirebaseDatabase.getInstance().getReference().child("users").child(task.result!!.user?.uid!!).child("userName").setValue(userNameEditText?.text.toString())
+ login()
+ }else{
+ Toast.makeText(this,"Login failed. Try again", Toast.LENGTH_SHORT).show()
+ }
+ }
+ }
+ }
+ }
+
+ fun login(){
+ //Move to next activity
+ val intent = Intent(this, SnapsActivity::class.java)
+ startActivity(intent)
+ }
+}
\ No newline at end of file
diff --git a/android_apps/SnapChatClone/app/src/main/java/com/example/snapchatclone/SnapsActivity.kt b/android_apps/SnapChatClone/app/src/main/java/com/example/snapchatclone/SnapsActivity.kt
new file mode 100644
index 000000000..1ad505db2
--- /dev/null
+++ b/android_apps/SnapChatClone/app/src/main/java/com/example/snapchatclone/SnapsActivity.kt
@@ -0,0 +1,93 @@
+package com.example.snapchatclone
+
+import android.content.Intent
+import androidx.appcompat.app.AppCompatActivity
+import android.os.Bundle
+import android.view.ContextMenu
+import android.view.Menu
+import android.view.MenuItem
+import android.widget.Adapter
+import android.widget.AdapterView
+import android.widget.ArrayAdapter
+import android.widget.ListView
+import com.google.firebase.auth.FirebaseAuth
+import com.google.firebase.database.ChildEventListener
+import com.google.firebase.database.DataSnapshot
+import com.google.firebase.database.DatabaseError
+import com.google.firebase.database.FirebaseDatabase
+
+class SnapsActivity : AppCompatActivity() {
+ val mAuth = FirebaseAuth.getInstance()
+ var snapsListView:ListView ?= null;
+ //var emailList:ArrayList = ArrayList();
+ var userNameList:ArrayList = ArrayList()
+ var snaps:ArrayList = ArrayList()
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_snaps)
+
+ snapsListView = findViewById(R.id.snapListView)
+ val arrayAdapter = ArrayAdapter(this,android.R.layout.simple_list_item_1,userNameList);
+ snapsListView?.adapter = arrayAdapter
+
+ FirebaseDatabase.getInstance().getReference().child("users").child(mAuth?.currentUser!!.uid).child("snaps").addChildEventListener(object : ChildEventListener {
+ override fun onChildAdded(snapshot: DataSnapshot, previousChildName: String?) {
+ userNameList.add(snapshot.child("from").value as String)
+ snaps.add(snapshot)
+ arrayAdapter.notifyDataSetChanged()
+ }
+ override fun onChildChanged(snapshot: DataSnapshot, previousChildName: String?) {}
+ override fun onChildRemoved(snapshot: DataSnapshot) {
+ var index = 0;
+ for(snap:DataSnapshot in snaps){
+ if(snap.key == snapshot.key){
+ snaps.removeAt(index)
+ userNameList.removeAt(index)
+ }
+ index++;
+ }
+ arrayAdapter.notifyDataSetChanged()
+ }
+ override fun onChildMoved(snapshot: DataSnapshot, previousChildName: String?) {}
+ override fun onCancelled(error: DatabaseError) {}
+ })
+ snapsListView?.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id ->
+ FirebaseDatabase.getInstance().getReference()
+ val snapshot = snaps.get(position)
+ var intent = Intent(this, ViewSnapActivity::class.java)
+
+ intent.putExtra("imageName",snapshot.child("imageName").value as String)
+ intent.putExtra("imageUrl",snapshot.child("imageUrl").value as String)
+ intent.putExtra("message",snapshot.child("message").value as String)
+ intent.putExtra("snapKey",snapshot.key)
+
+ startActivity(intent)
+ }
+ }
+
+ override fun onCreateOptionsMenu(menu: Menu?):Boolean{
+ val inflater = menuInflater;
+ inflater.inflate(R.menu.snaps,menu)
+ return super.onCreateOptionsMenu(menu)
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+
+ if(item?.itemId == R.id.createSnap){
+ val intent = Intent(this,CreateSnapActivity::class.java)
+ startActivity(intent)
+ }else if(item?.itemId == R.id.logout){
+ mAuth.signOut()
+ finish()
+ }
+
+ return super.onOptionsItemSelected(item)
+ }
+
+ override fun onBackPressed() {
+ mAuth.signOut()
+ super.onBackPressed()
+ }
+
+}
\ No newline at end of file
diff --git a/android_apps/SnapChatClone/app/src/main/java/com/example/snapchatclone/ViewSnapActivity.kt b/android_apps/SnapChatClone/app/src/main/java/com/example/snapchatclone/ViewSnapActivity.kt
new file mode 100644
index 000000000..9f123062e
--- /dev/null
+++ b/android_apps/SnapChatClone/app/src/main/java/com/example/snapchatclone/ViewSnapActivity.kt
@@ -0,0 +1,70 @@
+package com.example.snapchatclone
+
+import android.graphics.Bitmap
+import android.graphics.BitmapFactory
+import android.os.AsyncTask
+import androidx.appcompat.app.AppCompatActivity
+import android.os.Bundle
+import android.view.View
+import android.widget.ImageView
+import android.widget.TextView
+import com.bumptech.glide.Glide
+import com.google.firebase.auth.FirebaseAuth
+import com.google.firebase.database.FirebaseDatabase
+import com.google.firebase.storage.FirebaseStorage
+import java.lang.Exception
+import java.net.HttpURLConnection
+import java.net.URL
+
+
+class ViewSnapActivity : AppCompatActivity() {
+ var messageTextView: TextView? = null
+ var mAuth = FirebaseAuth.getInstance()
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_new_snap)
+
+ messageTextView = findViewById(R.id.messageTextView)
+ var snapsImageView: ImageView = findViewById(R.id.snapImageView)
+
+ messageTextView?.text = intent.getStringExtra("message")
+
+ var url = intent.getStringExtra("imageUrl")
+ Glide.with(this).load(url).dontAnimate().dontTransform().into(snapsImageView)
+ // Glide.with(.getContext()).load(url).placeholder(R.drawable.default_profile).dontAnimate().into(view);
+ }
+
+ /*val task = ImageDownoader()
+ val myImage: Bitmap
+ try {
+ myImage = task.execute(intent.getStringExtra("imageUrl")).get()
+ snapsImageView?.setImageBitmap(myImage)
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+
+ }
+
+ inner class ImageDownoader : AsyncTask() {
+ override fun doInBackground(vararg urls: String?): Bitmap? {
+ try {
+ val url = URL(urls[0])
+ val connection = url.openConnection() as HttpURLConnection
+ connection.connect()
+ val `is` = connection.inputStream
+ return BitmapFactory.decodeStream(`is`)
+ } catch (e: Exception) {
+ e.printStackTrace()
+ return null
+ }
+ }
+ }*/
+
+ override fun onBackPressed() {
+ super.onBackPressed()
+
+ intent.getStringExtra("snapKey")?.let { FirebaseDatabase.getInstance().getReference().child("users").child(mAuth?.currentUser!!.uid).child("snaps").child(it).removeValue() }
+ intent.getStringExtra("imageName")?.let { FirebaseStorage.getInstance().getReference().child("Images").child(it).delete() }
+ }
+}
diff --git a/android_apps/SnapChatClone/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/android_apps/SnapChatClone/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 000000000..2b068d114
--- /dev/null
+++ b/android_apps/SnapChatClone/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android_apps/SnapChatClone/app/src/main/res/drawable/ic_launcher_background.xml b/android_apps/SnapChatClone/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 000000000..07d5da9cb
--- /dev/null
+++ b/android_apps/SnapChatClone/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android_apps/SnapChatClone/app/src/main/res/layout/activity_chose_user.xml b/android_apps/SnapChatClone/app/src/main/res/layout/activity_chose_user.xml
new file mode 100644
index 000000000..9f87d96c8
--- /dev/null
+++ b/android_apps/SnapChatClone/app/src/main/res/layout/activity_chose_user.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/android_apps/SnapChatClone/app/src/main/res/layout/activity_create_snap.xml b/android_apps/SnapChatClone/app/src/main/res/layout/activity_create_snap.xml
new file mode 100644
index 000000000..f2e729330
--- /dev/null
+++ b/android_apps/SnapChatClone/app/src/main/res/layout/activity_create_snap.xml
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android_apps/SnapChatClone/app/src/main/res/layout/activity_main.xml b/android_apps/SnapChatClone/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 000000000..b50695255
--- /dev/null
+++ b/android_apps/SnapChatClone/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android_apps/SnapChatClone/app/src/main/res/layout/activity_new_snap.xml b/android_apps/SnapChatClone/app/src/main/res/layout/activity_new_snap.xml
new file mode 100644
index 000000000..d48a14ac8
--- /dev/null
+++ b/android_apps/SnapChatClone/app/src/main/res/layout/activity_new_snap.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android_apps/SnapChatClone/app/src/main/res/layout/activity_snaps.xml b/android_apps/SnapChatClone/app/src/main/res/layout/activity_snaps.xml
new file mode 100644
index 000000000..cb00cce84
--- /dev/null
+++ b/android_apps/SnapChatClone/app/src/main/res/layout/activity_snaps.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/android_apps/SnapChatClone/app/src/main/res/menu/snaps.xml b/android_apps/SnapChatClone/app/src/main/res/menu/snaps.xml
new file mode 100644
index 000000000..600cbd86d
--- /dev/null
+++ b/android_apps/SnapChatClone/app/src/main/res/menu/snaps.xml
@@ -0,0 +1,10 @@
+
+
\ No newline at end of file
diff --git a/android_apps/SnapChatClone/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android_apps/SnapChatClone/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 000000000..eca70cfe5
--- /dev/null
+++ b/android_apps/SnapChatClone/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/android_apps/SnapChatClone/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/android_apps/SnapChatClone/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 000000000..eca70cfe5
--- /dev/null
+++ b/android_apps/SnapChatClone/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/android_apps/SnapChatClone/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android_apps/SnapChatClone/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000000000000000000000000000000000000..a571e60098c92c2baca8a5df62f2929cbff01b52
GIT binary patch
literal 3593
zcmV+k4)*bhP){4Q1@|o^l5vR(0JRNCL<7M6}UD`@%^5zYjRJ-VNC3qn#9n=m>>ACRx!M
zlW3!lO>#0MCAqh6PU7cMP#aQ`+zp##c~|0RJc4JAuaV=qZS|vg8XJ$1pYxc-u~Q5j
z%Ya4ddEvZow!floOU_jrlE84*Kfv6!kMK^%#}A$Bjrna`@pk(TS$jA@P;|iPUR-x)_r4ELtL9aUonVhI31zFsJ96
z|5S{%9|FB-SsuD=#0u1WU!W6fcXF)#63D7tvwg%1l(}|SzXh_Z(5234`w*&@ctO>g
z0Aug~xs*zAjCpNau(Ul@mR~?6dNGx9Ii5MbMvmvUxeqy>$Hrrn;v8G!g*o~UV4mr_
zyWaviS4O6Kb?ksg`)0wj?E@IYiw3az(r1w37|S|7!ODxfW%>6m?!@woyJUIh_!>E$
z+vYyxcpe*%QHt~E*etx=mI~XG8~QJhRar>tNMB;pPOKRfXjGt4fkp)y6=*~XIJC&C!aaha9k7~UP9;`q;1n9prU@a%Kg%gDW+xy9n`kiOj8WIs;+T>HrW
znVTomw_2Yd%+r4at4zQC3*=Z4naYE7H*Dlv4=@IEtH_H;af}t@W7@mE$1xI#XM-`%
z0le3-Q}*@D@ioThJ*cgm>kVSt+=txjd2BpJDbBrpqp-xV9X6Rm?1Mh~?li96xq(IP
z+n(4GTXktSt_z*meC5=$pMzMKGuIn&_IeX6Wd!2$md%l{x(|LXClGVhzqE^Oa@!*!
zN%O7K8^SHD|9aoAoT4QLzF+Uh_V03V;KyQ|__-RTH(F72qnVypVei#KZ2K-7YiPS*
z-4gZd>%uRm<0iGmZH|~KW<>#hP9o@UT@gje_^AR{?p(v|y8`asyNi4G?n#2V+jsBa
z+uJ|m;EyHnA%QR7{z(*%+Z;Ip(Xt5n<`4yZ51n^!%L?*a=)Bt{J_b`;+~$Z7h^x@&
zSBr2>_@&>%7=zp5Ho5H~6-Y@wXkpt{s9Tc+7RnfWuZC|&NO6p{m-gU%=cPw3qyB>1
zto@}!>_e`99vhEQic{;8goXMo1NA`>sch8T3@O44!$uf`IlgBj#c@Ku*!9B`7seRe
z2j?cKG4R-Uj8dFidy25wu#J3>-_u`WT%NfU54JcxsJv;A^i#t!2XXn%zE=O##OXoy
zwR2+M!(O12D_LUsHV)v2&TBZ*di1$c8
z+_~Oo@HcOFV&TasjNRjf*;zVV?|S@-_EXmlIG@&F!WS#yU9<_Ece?sq^L^Jf%(##=
zdTOpA6uXwXx3O|`C-Dbl~`~#9yjlFN>;Yr?Kv68=F`fQLW
z(x40UIAuQRN~Y|fpCi2++qHWrXd&S*NS$z8V+YP
zSX7#fxfebdJfrw~mzZr!thk9BE&_eic@-9C0^nK@0o$T5nAK~CHV4fzY#KJ=^uV!D
z3)jL(DDpL!TDSq`=e0v8(8`Wo_~p*6KHyT!kmCCCU48I?mw-UrBj8=Vg#?O%Z2<|C
z?+4Q&W09VsK<14)vHY^n;Zi3%4Q?s4x^$3;acx76-t*K|3^MUKELf>Jew${&!(xTD_PD>KINXl?sUX;X6(}jr
zKrxdFCW8)!)dz>b!b9nBj1uYxc;
zCkmbfhwNZDp*
zIG07ixjYK$3PNQx)KxK1*Te{mTeb}BZJ++Waj0sFgVkw&DAWDnl0pBiBWqxObPX)h
z*TN!$aBLmH2kNX4xMpc!d15^*Gksy1l@P~U&INWk{u*%*5>+Aqn=LEne
zClEHdguEb8oEZgNsY0NjWUMIEh&hLsm2Ght7L+H$y*w6nWjffE>tJ6IF2bRboPSlg
z;8~Xh^J6|kbIX-0hD~-L?Y;aST2{Rivf_k4>}dA%URJ#mvcu^R*wO6iy{vjCWaoSe
zIzRNGW!00Ad0EXUi-mouPFz-|lzU9e0x_*DNL*smDnbNRbrdEYSuu3?q}5FcaLx&n
z6o+$;B9jEl3Xl|sbB;2b1fnV>B@X8tbpg!?+EPe~!#T&jf&`-3(^s5eOsfnL9BZO5
z<?!X^iNgt5T^IrT!Z1m3I3c@N#=*Wk
zTtb{+Os~=ijjE^lB2QE@pTLB>vqLE(X}Ul(PxsQZDCnRJoyWpo%5ub6koe;ZUTN6o;49
z%&K@2C_+LULQSaPbZ$5a#EF|k;vjo+j;&bEgJpe=Dlb&rmCN}Yml6`FSSKkCFRPi=
z31Y?SD~<-!YoCBXgYhw7kJe3M?qILPK4)%D3{=?~aXC5Wgu;<#4Lf9~Ghw37nNM&o
z(80MdTm&yGb#a6!4*MJ~aIJ`eYb7HVu2r#ctB!;Bxoucjw;3~P<1wQy0q*sQ
z-8i2F_l87aanncS%?9u}>B0ISxxWC)h0qo
zrToFN(!i`X6lQgyd`nhvZivH_^!NKOkY(B6epkb-IT>nNDsn!@k(QQ{wh(eY$F)2L
z%JK*qpF;wXQ&v$amkWn9MR
zaNbc-m6G;3A@HbAhN>=FN*tK8Kuz(Oa%{~&W>Cn+r}2e4u5KK(akX-yq^zQ4DCcwB
zC?TsVB4vEeeSxS_^$~}*LFNtJ0!>a^k=k#8$c8T#XHavvV16Nda6bl2B5~loOSuzO
zELE{i*5|lY#X(gWDdTfA@Hn5+Es&8oX6Na#Nhdn#w^HUT=U69h_kQVdztsB&!awcK
zhE$2-v_uFjRBxzT6NNb)AND!l0}@y8&8iWGR`$$Kl_KCnY(6UaWtqaj6b
zs*e#kA#=_#KTn{U!{V4VXkq!qx>|~Hj2P?V{?LHuK~EOwt8K?a=Xztlp31x-RhD0*-wJ+j>Y?-0hXd`O?21C+SsD+I(m2?agwd{C
zOB+u@xsG_9xP@3yLwmg%s#MkFt7;-CAxBZpA)JebBVkF?7I-#pgkwW2oEiyDaUzt}
zk+4W#SNAW)n+lH6T5J8{bNxA9w|@PP^za&C{2LmVpz%AG?wzpT`>@HLcMqBD^G-9}
zw>-__!0I%9ZnAe-_hZjZP4nNGYJ^AgtAO?>Uo^!N|Le+X|9-g?II=KWY+eRb@sf8iJh{v#I?
zC%*LZ_}5?l+Z(UF^4EXA`uArU90SL~F%8D=fjmD#FnWw0qsQp+OdS6QzyUa+`7Q|u
P00000NkvXXu0mjfP=x?Y
literal 0
HcmV?d00001
diff --git a/android_apps/SnapChatClone/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/android_apps/SnapChatClone/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000000000000000000000000000000000000..61da551c5594a1f9d26193983d2cd69189014603
GIT binary patch
literal 5339
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