diff --git a/app/FunnyPrankSounds.jks b/app/FunnyPrankSounds.jks new file mode 100644 index 0000000..cb3ee3b Binary files /dev/null and b/app/FunnyPrankSounds.jks differ diff --git a/app/build.gradle.kts b/app/build.gradle.kts index a6b6803..65e523e 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -15,7 +15,7 @@ android { targetSdk = 34 versionCode = 1 versionName = "1.0.0" - setProperty("archivesBaseName", "Funny Prank Sounds" + versionName + "(${versionCode})_$timestamp") + setProperty("archivesBaseName", "Funny Prank Sounds " + versionName + "(${versionCode})_$timestamp") testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } @@ -53,4 +53,6 @@ dependencies { implementation ("androidx.room:room-runtime:2.6.1") annotationProcessor ("androidx.room:room-compiler:2.6.1") + + implementation("com.airbnb.android:lottie:6.5.0") } \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 481bb43..87240f6 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -18,4 +18,16 @@ # If you keep the line number information, uncomment this to # hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file +#-renamesourcefileattribute SourceFile + +-keepclassmembers class com.prank.funnypranksounds.MyApplication { + public static final java.lang.String Database_Name; + public static final int Database_Version; +} +-keepclassmembers class * { + @androidx.room.Query ; +} +-keep class com.prank.funnypranksounds.data.local.database.AppDatabase { *; } +-keep class com.prank.funnypranksounds.data.local.entity.AudioData { *; } +-keep class com.prank.funnypranksounds.data.local.dao.AudioDataDao { *; } +-dontwarn javax.annotation.Nullable diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 71ff386..016805d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -23,6 +23,12 @@ android:supportsRtl="true" android:theme="@style/Theme.FunnyPrankSounds" tools:targetApi="31"> + + diff --git a/app/src/main/java/com/prank/funnypranksounds/MyApplication.java b/app/src/main/java/com/prank/funnypranksounds/MyApplication.java index 1499a20..d47ff99 100644 --- a/app/src/main/java/com/prank/funnypranksounds/MyApplication.java +++ b/app/src/main/java/com/prank/funnypranksounds/MyApplication.java @@ -38,7 +38,6 @@ public class MyApplication extends Application { private void initDatabase() { AudioRepository imageRepository = new AudioRepository(getContext()); List audioDataList = JsonParser.parseJson("prank.json"); - Log.d("appliacation", "data: " + audioDataList); imageRepository.insertAll(audioDataList); } diff --git a/app/src/main/java/com/prank/funnypranksounds/data/local/dao/AudioDataDao.java b/app/src/main/java/com/prank/funnypranksounds/data/local/dao/AudioDataDao.java index c1001ac..92961b2 100644 --- a/app/src/main/java/com/prank/funnypranksounds/data/local/dao/AudioDataDao.java +++ b/app/src/main/java/com/prank/funnypranksounds/data/local/dao/AudioDataDao.java @@ -2,6 +2,7 @@ package com.prank.funnypranksounds.data.local.dao; import androidx.lifecycle.LiveData; import androidx.room.Dao; +import androidx.room.Delete; import androidx.room.Insert; import androidx.room.Query; import androidx.room.Update; @@ -16,9 +17,15 @@ public interface AudioDataDao { @Insert void insertAll(List audioDataList); + @Insert + void insert(AudioData audioData); + @Update void update(AudioData audioData); + @Delete + void delete(AudioData audioData); + @Query("SELECT * FROM AudioData WHERE id IN (SELECT MIN(id) FROM AudioData GROUP BY categoryName)") LiveData> getFirstCategory(); @@ -27,4 +34,10 @@ public interface AudioDataDao { @Query("SELECT * FROM AudioData WHERE isFavorite = 1") LiveData> getFavorite(); + + @Query("SELECT * FROM AudioData WHERE isExternal = 1") + LiveData> getExternal(); + + @Query("SELECT COUNT(*) FROM AudioData WHERE mp3Url = :uri") + int getCount(String uri); } diff --git a/app/src/main/java/com/prank/funnypranksounds/data/local/entity/AudioData.java b/app/src/main/java/com/prank/funnypranksounds/data/local/entity/AudioData.java index 9ac8f5d..65c1b4d 100644 --- a/app/src/main/java/com/prank/funnypranksounds/data/local/entity/AudioData.java +++ b/app/src/main/java/com/prank/funnypranksounds/data/local/entity/AudioData.java @@ -16,14 +16,16 @@ public class AudioData implements Serializable { private String mp3Url; private String preUrl; private boolean isFavorite; + private boolean isExternal; - public AudioData(String categoryName, String categoryUrl, String title, String mp3Url, String preUrl, boolean isFavorite) { + public AudioData(String categoryName, String categoryUrl, String title, String mp3Url, String preUrl, boolean isFavorite, boolean isExternal) { this.categoryName = categoryName; this.categoryUrl = categoryUrl; this.title = title; this.mp3Url = mp3Url; this.preUrl = preUrl; this.isFavorite = isFavorite; + this.isExternal = isExternal; } public int getId() { @@ -81,4 +83,12 @@ public class AudioData implements Serializable { public void setFavorite(boolean favorite) { isFavorite = favorite; } + + public boolean isExternal() { + return isExternal; + } + + public void setExternal(boolean external) { + isExternal = external; + } } diff --git a/app/src/main/java/com/prank/funnypranksounds/data/repository/AudioRepository.java b/app/src/main/java/com/prank/funnypranksounds/data/repository/AudioRepository.java index 9a4b808..c329f83 100644 --- a/app/src/main/java/com/prank/funnypranksounds/data/repository/AudioRepository.java +++ b/app/src/main/java/com/prank/funnypranksounds/data/repository/AudioRepository.java @@ -1,6 +1,8 @@ package com.prank.funnypranksounds.data.repository; import android.content.Context; +import android.os.Handler; +import android.os.Looper; import androidx.lifecycle.LiveData; @@ -9,20 +11,28 @@ import com.prank.funnypranksounds.data.local.database.AppDatabase; import com.prank.funnypranksounds.data.local.entity.AudioData; import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; public class AudioRepository { private final AudioDataDao dao; + private final ExecutorService executorService; public AudioRepository(Context context) { AppDatabase appDatabase = AppDatabase.getInstance(context); dao = appDatabase.audioDataDao(); + executorService = Executors.newSingleThreadExecutor(); } public void insertAll(List audioDataList) { new Thread(() -> dao.insertAll(audioDataList)).start(); } + public void insert(AudioData audioData) { + new Thread(() -> dao.insert(audioData)).start(); + } + public void update(AudioData audioData) { new Thread(() -> dao.update(audioData)).start(); } @@ -39,4 +49,23 @@ public class AudioRepository { return dao.getFavorite(); } + public void getCountAsync(String uri, CountCallback callback) { + executorService.execute(() -> { + int count = dao.getCount(uri); + new Handler(Looper.getMainLooper()).post(() -> callback.onCountFetched(count)); + }); + } + + public interface CountCallback { + void onCountFetched(int count); + } + + public LiveData> getExternal() { + return dao.getExternal(); + } + + public void delete(AudioData audioData){ + new Thread(() -> dao.delete(audioData)).start(); + } + } diff --git a/app/src/main/java/com/prank/funnypranksounds/ui/activity/MainActivity.java b/app/src/main/java/com/prank/funnypranksounds/ui/activity/MainActivity.java index 53548b6..8be8d75 100644 --- a/app/src/main/java/com/prank/funnypranksounds/ui/activity/MainActivity.java +++ b/app/src/main/java/com/prank/funnypranksounds/ui/activity/MainActivity.java @@ -81,7 +81,7 @@ public class MainActivity extends AppCompatActivity { int iconResId = getIconResource(tab.getPosition(), isSelected); tabBinding.imageView.setImageResource(iconResId); - int textColor = isSelected ? getResources().getColor(R.color.black, null) : getResources().getColor(R.color.gray, null); + int textColor = isSelected ? getResources().getColor(R.color.yellow, null) : getResources().getColor(R.color.gray, null); tabBinding.text.setTextColor(textColor); } } @@ -114,17 +114,17 @@ public class MainActivity extends AppCompatActivity { switch (position) { case 0: tabCustomBinding.imageView.setImageResource(R.drawable.category); - tabCustomBinding.text.setText("Category"); - tabCustomBinding.text.setTextColor(getResources().getColor(R.color.black, null)); + tabCustomBinding.text.setText(R.string.category); + tabCustomBinding.text.setTextColor(getResources().getColor(R.color.yellow, null)); break; case 1: - tabCustomBinding.imageView.setImageResource(R.drawable.audio); - tabCustomBinding.text.setText("Audio"); + tabCustomBinding.imageView.setImageResource(R.drawable.un_audio); + tabCustomBinding.text.setText(R.string.audio); tabCustomBinding.text.setTextColor(getResources().getColor(R.color.gray, null)); break; case 2: tabCustomBinding.imageView.setImageResource(R.drawable.un_collection); - tabCustomBinding.text.setText("Collection"); + tabCustomBinding.text.setText(R.string.collection); tabCustomBinding.text.setTextColor(getResources().getColor(R.color.gray, null)); break; } diff --git a/app/src/main/java/com/prank/funnypranksounds/ui/activity/RecordAudioActivity.java b/app/src/main/java/com/prank/funnypranksounds/ui/activity/RecordAudioActivity.java new file mode 100644 index 0000000..b49c938 --- /dev/null +++ b/app/src/main/java/com/prank/funnypranksounds/ui/activity/RecordAudioActivity.java @@ -0,0 +1,155 @@ +package com.prank.funnypranksounds.ui.activity; + +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.media.MediaRecorder; +import android.os.Bundle; +import android.os.Handler; + +import androidx.activity.EdgeToEdge; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; +import androidx.core.graphics.Insets; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowInsetsCompat; +import androidx.lifecycle.ViewModelProvider; + +import com.prank.funnypranksounds.R; +import com.prank.funnypranksounds.databinding.ActivityRecordAudioBinding; +import com.prank.funnypranksounds.utils.AudioUtils; +import com.prank.funnypranksounds.viewmodel.AudioViewModel; + +import java.io.File; +import java.io.IOException; + +public class RecordAudioActivity extends AppCompatActivity { + + private ActivityRecordAudioBinding binding; + private boolean isStarted; + private long time; + private final Handler handler = new Handler(); + private MediaRecorder mediaRecorder; + private File outputFile; + + private static final int REQUEST_RECORD_AUDIO_PERMISSION = 200; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + binding = ActivityRecordAudioBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + EdgeToEdge.enable(this); + ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { + Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); + v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); + return insets; + }); + + initData(); + initEvent(); + + } + + private void initData() { + } + + private void initEvent() { + + binding.voice.setOnClickListener(v -> { + if (ContextCompat.checkSelfPermission(RecordAudioActivity.this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { + ActivityCompat.requestPermissions(RecordAudioActivity.this, new String[]{Manifest.permission.RECORD_AUDIO}, REQUEST_RECORD_AUDIO_PERMISSION); + } else { + toggleRecording(); + } + }); + + binding.back.setOnClickListener(v -> onBackPressed()); + } + + private void toggleRecording() { + if (isStarted) { + stopRecording(); + } else { + startRecording(); + } + isStarted = !isStarted; + } + + private final Runnable updateTimeTask = new Runnable() { + @Override + public void run() { + long currentTime = System.currentTimeMillis(); + long elapsedTime = currentTime - time; + binding.time.setText(AudioUtils.formatTime(elapsedTime)); + handler.postDelayed(this, 1000); + } + }; + + private void startRecording() { + try { + mediaRecorder = new MediaRecorder(); + mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); + mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); + mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); + + String fileName = "recording_" + System.currentTimeMillis() + ".m4a"; + outputFile = new File(getFilesDir(), fileName); + mediaRecorder.setOutputFile(outputFile.getAbsolutePath()); + + mediaRecorder.prepare(); + mediaRecorder.start(); + + time = System.currentTimeMillis(); + handler.post(updateTimeTask); + binding.animationView.playAnimation(); + + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void stopRecording() { + if (mediaRecorder != null) { + mediaRecorder.stop(); + mediaRecorder.release(); + mediaRecorder = null; + } + + handler.removeCallbacks(updateTimeTask); + binding.animationView.cancelAnimation(); + binding.animationView.setFrame(0); + binding.time.setText(R.string._00_00_00); + + Intent intent = new Intent(RecordAudioActivity.this, SaveAudioActivity.class); + intent.putExtra("audioFilePath", outputFile.getAbsolutePath()); + startActivity(intent); + } + + @Override + public void onBackPressed() { + super.onBackPressed(); + if (isStarted) { + if (mediaRecorder != null) { + mediaRecorder.stop(); + mediaRecorder.release(); + mediaRecorder = null; + } + deleteRecordingFile(); + } + finish(); + } + + private void deleteRecordingFile() { + if (outputFile != null && outputFile.exists()) { + boolean deleted = outputFile.delete(); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + binding = null; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/prank/funnypranksounds/ui/activity/SaveAudioActivity.java b/app/src/main/java/com/prank/funnypranksounds/ui/activity/SaveAudioActivity.java new file mode 100644 index 0000000..11d26fc --- /dev/null +++ b/app/src/main/java/com/prank/funnypranksounds/ui/activity/SaveAudioActivity.java @@ -0,0 +1,181 @@ +package com.prank.funnypranksounds.ui.activity; + +import android.content.Intent; +import android.media.MediaPlayer; +import android.os.Bundle; +import android.util.Log; +import android.widget.Toast; + +import androidx.activity.EdgeToEdge; +import androidx.activity.OnBackPressedCallback; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.graphics.Insets; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowInsetsCompat; +import androidx.lifecycle.ViewModelProvider; + +import com.prank.funnypranksounds.R; +import com.prank.funnypranksounds.data.local.database.AppDatabase; +import com.prank.funnypranksounds.data.local.entity.AudioData; +import com.prank.funnypranksounds.databinding.ActivitySaveAudioBinding; +import com.prank.funnypranksounds.utils.AudioUtils; +import com.prank.funnypranksounds.viewmodel.AudioViewModel; + +import java.io.File; +import java.io.IOException; + +public class SaveAudioActivity extends AppCompatActivity { + + private ActivitySaveAudioBinding binding; + private AudioViewModel audioViewModel; + private String audioFilePath; + private String inputText; + private MediaPlayer mediaPlayer; + private boolean isPlaying; + private int duration; + private boolean isSaved; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + binding = ActivitySaveAudioBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + EdgeToEdge.enable(this); + ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { + Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); + v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); + return insets; + }); + + initData(); + initEvent(); + + } + + private void initData() { + audioFilePath = getIntent().getStringExtra("audioFilePath"); + if (audioFilePath == null) { + Toast.makeText(this, "The audio file path is invalid", Toast.LENGTH_SHORT).show(); + return; + } + + File audioFile = new File(audioFilePath); + if (!audioFile.exists()) { + Toast.makeText(this, "Audio file does not exist", Toast.LENGTH_SHORT).show(); + finish(); + return; + } + + audioViewModel = new ViewModelProvider(this, new ViewModelProvider.AndroidViewModelFactory(getApplication())) + .get(AudioViewModel.class); + + } + + private void initEvent() { + binding.back.setOnClickListener(v -> handleBackPressed()); + binding.play.setOnClickListener(v -> playOrPauseAudio()); + + binding.save.setOnClickListener(v -> { + inputText = binding.editText.getText().toString(); + if (inputText.trim().isEmpty()) { + Toast.makeText(getApplicationContext(), "The name cannot be empty", Toast.LENGTH_SHORT).show(); + return; + } + + audioViewModel.insert(new AudioData(inputText, audioFilePath, inputText, audioFilePath, "", false, true)); + + isSaved = true; + + Intent intent = new Intent(SaveAudioActivity.this, MainActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); + startActivity(intent); + finish(); + }); + + displayAudioDuration(); + + getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) { + @Override + public void handleOnBackPressed() { + handleBackPressed(); + } + }); + } + + private void displayAudioDuration() { + if (audioFilePath != null) { + mediaPlayer = new MediaPlayer(); + try { + mediaPlayer.setDataSource(audioFilePath); + mediaPlayer.prepare(); + + duration = mediaPlayer.getDuration(); + binding.time.setText(AudioUtils.formatTime(duration)); + + } catch (IOException e) { + e.printStackTrace(); + Toast.makeText(this, "Unable to load audio", Toast.LENGTH_SHORT).show(); + } + } else { + Toast.makeText(this, "The audio file path is invalid", Toast.LENGTH_SHORT).show(); + } + } + + private void handleBackPressed() { + deleteRecordingFile(); + finish(); + } + + private void deleteRecordingFile() { + File file = new File(audioFilePath); + if (file.exists()) { + boolean deleted = file.delete(); + } + } + + private void playOrPauseAudio() { + if (isPlaying) { + mediaPlayer.pause(); + binding.play.setImageResource(R.drawable.play); + isPlaying = false; + } else { + if (mediaPlayer == null) { + mediaPlayer = new MediaPlayer(); + try { + mediaPlayer.setDataSource(audioFilePath); + mediaPlayer.prepare(); + } catch (IOException e) { + e.printStackTrace(); + Toast.makeText(this, "Unable to play audio", Toast.LENGTH_SHORT).show(); + return; + } + } + + mediaPlayer.start(); + binding.play.setImageResource(R.drawable.pause); + isPlaying = true; + + mediaPlayer.setOnCompletionListener(mp -> { + Toast.makeText(this, "Play completed", Toast.LENGTH_SHORT).show(); + binding.play.setImageResource(R.drawable.play); + isPlaying = false; + }); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + if (mediaPlayer != null) { + if (isPlaying) { + mediaPlayer.stop(); + } + mediaPlayer.release(); + mediaPlayer = null; + } + if (!isSaved) { + deleteRecordingFile(); + } + binding = null; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/prank/funnypranksounds/ui/activity/SplashActivity.java b/app/src/main/java/com/prank/funnypranksounds/ui/activity/SplashActivity.java index 43ee20f..04608dc 100644 --- a/app/src/main/java/com/prank/funnypranksounds/ui/activity/SplashActivity.java +++ b/app/src/main/java/com/prank/funnypranksounds/ui/activity/SplashActivity.java @@ -19,7 +19,7 @@ import com.prank.funnypranksounds.databinding.ActivitySplashBinding; public class SplashActivity extends AppCompatActivity { private ActivitySplashBinding binding; - private static final long TOTAL_TIME = 1000; + private static final long TOTAL_TIME = 3000; private CountDownTimer countDownTimer; @Override diff --git a/app/src/main/java/com/prank/funnypranksounds/ui/adapter/AudioAdapter.java b/app/src/main/java/com/prank/funnypranksounds/ui/adapter/AudioAdapter.java index 3b58de1..b70ac23 100644 --- a/app/src/main/java/com/prank/funnypranksounds/ui/adapter/AudioAdapter.java +++ b/app/src/main/java/com/prank/funnypranksounds/ui/adapter/AudioAdapter.java @@ -10,6 +10,8 @@ import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.RecyclerView; import com.bumptech.glide.Glide; @@ -29,6 +31,7 @@ public class AudioAdapter extends RecyclerView.Adapter private final Context context; private final Activity activity; private final int type; + private final int[] colors; public AudioAdapter(List audioDataList, AudioViewModel audioViewModel, Context context, Activity activity, int type) { this.context = context; @@ -36,6 +39,16 @@ public class AudioAdapter extends RecyclerView.Adapter this.audioDataList = audioDataList; this.activity = activity; this.type = type; + + colors = new int[]{ + R.color.color1, + R.color.color2, + R.color.color3, + R.color.color4, + R.color.color5, + R.color.color6, + R.color.color7 + }; } public void updateData(List newAudioDataList) { @@ -61,7 +74,7 @@ public class AudioAdapter extends RecyclerView.Adapter name = audioData.getTitle(); } - holder.bind(audioData, name); + holder.bind(audioData, name,position); } @Override @@ -73,20 +86,27 @@ public class AudioAdapter extends RecyclerView.Adapter ImageView imageView; ImageView like; TextView textView; + ConstraintLayout constraintLayout; ViewHolder(View itemView) { super(itemView); imageView = itemView.findViewById(R.id.imageView); like = itemView.findViewById(R.id.like); textView = itemView.findViewById(R.id.textView); + constraintLayout = itemView.findViewById(R.id.main); } - void bind(AudioData audioData, String name) { - String audioDataImagePath = audioData.getCategoryUrl(); + void bind(AudioData audioData, String name,int position) { + String audioDataImagePath = ""; + textView.setVisibility(View.VISIBLE); + setItemText(name); - if (type == 0 || type == 1) { - textView.setVisibility(View.VISIBLE); - setItemText(name); + constraintLayout.setBackgroundTintList(ContextCompat.getColorStateList(context, colors[position % colors.length])); + + if (type == 0) { + audioDataImagePath = audioData.getCategoryUrl(); + }else if (type == 1){ + audioDataImagePath = audioData.getPreUrl(); } loadImage(audioDataImagePath); diff --git a/app/src/main/java/com/prank/funnypranksounds/ui/callback/AudioItemCallback.java b/app/src/main/java/com/prank/funnypranksounds/ui/callback/AudioItemCallback.java new file mode 100644 index 0000000..e451fe1 --- /dev/null +++ b/app/src/main/java/com/prank/funnypranksounds/ui/callback/AudioItemCallback.java @@ -0,0 +1,33 @@ +package com.prank.funnypranksounds.ui.callback; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.ItemTouchHelper; +import androidx.recyclerview.widget.RecyclerView; + +public class AudioItemCallback extends ItemTouchHelper.SimpleCallback { + + private final OnItemSwipeListener listener; + + public AudioItemCallback(OnItemSwipeListener listener) { + super(0, ItemTouchHelper.LEFT); + this.listener = listener; + } + + @Override + public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) { + return false; + } + + @Override + public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) { + int position = viewHolder.getAdapterPosition(); + if (listener != null) { + listener.onItemSwiped(position); + } + } + + public interface OnItemSwipeListener { + void onItemSwiped(int position); + } +} + diff --git a/app/src/main/java/com/prank/funnypranksounds/ui/fragment/AudioFragment.java b/app/src/main/java/com/prank/funnypranksounds/ui/fragment/AudioFragment.java index e9ee04d..0c7b712 100644 --- a/app/src/main/java/com/prank/funnypranksounds/ui/fragment/AudioFragment.java +++ b/app/src/main/java/com/prank/funnypranksounds/ui/fragment/AudioFragment.java @@ -1,66 +1,219 @@ package com.prank.funnypranksounds.ui.fragment; +import static android.app.Activity.RESULT_OK; + +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.Build; import android.os.Bundle; - -import androidx.fragment.app.Fragment; - import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.Toast; +import androidx.annotation.NonNull; +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.Observer; +import androidx.lifecycle.ViewModelProvider; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.ItemTouchHelper; + +import com.google.android.material.bottomsheet.BottomSheetDialog; import com.prank.funnypranksounds.R; +import com.prank.funnypranksounds.data.local.entity.AudioData; +import com.prank.funnypranksounds.data.repository.AudioRepository; +import com.prank.funnypranksounds.databinding.FragmentAudioBinding; +import com.prank.funnypranksounds.ui.activity.RecordAudioActivity; +import com.prank.funnypranksounds.ui.adapter.AudioAdapter; +import com.prank.funnypranksounds.ui.callback.AudioItemCallback; +import com.prank.funnypranksounds.utils.AudioUtils; +import com.prank.funnypranksounds.viewmodel.AudioViewModel; -/** - * A simple {@link Fragment} subclass. - * Use the {@link AudioFragment#newInstance} factory method to - * create an instance of this fragment. - */ -public class AudioFragment extends Fragment { +import java.util.ArrayList; +import java.util.List; - // TODO: Rename parameter arguments, choose names that match - // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER - private static final String ARG_PARAM1 = "param1"; - private static final String ARG_PARAM2 = "param2"; +public class AudioFragment extends Fragment implements AudioItemCallback.OnItemSwipeListener { - // TODO: Rename and change types of parameters - private String mParam1; - private String mParam2; - - public AudioFragment() { - // Required empty public constructor - } - - /** - * Use this factory method to create a new instance of - * this fragment using the provided parameters. - * - * @param param1 Parameter 1. - * @param param2 Parameter 2. - * @return A new instance of fragment AudioFragment. - */ - // TODO: Rename and change types and number of parameters - public static AudioFragment newInstance(String param1, String param2) { - AudioFragment fragment = new AudioFragment(); - Bundle args = new Bundle(); - args.putString(ARG_PARAM1, param1); - args.putString(ARG_PARAM2, param2); - fragment.setArguments(args); - return fragment; - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (getArguments() != null) { - mParam1 = getArguments().getString(ARG_PARAM1); - mParam2 = getArguments().getString(ARG_PARAM2); - } - } + private FragmentAudioBinding binding; + private AudioAdapter adapter; + private AudioViewModel audioViewModel; + private Uri audioUri; + private String fileName; + private List audioDataList = new ArrayList<>(); + private static final int REQUEST_CODE_READ_MEDIA_AUDIO = 1001; + private static final int REQUEST_CODE_PICK_AUDIO = 1002; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - // Inflate the layout for this fragment - return inflater.inflate(R.layout.fragment_audio, container, false); + + binding = FragmentAudioBinding.inflate(inflater, container, false); + + initData(); + initEvent(); + + return binding.getRoot(); + } + + private void initData() { + audioViewModel = new ViewModelProvider(this, new ViewModelProvider.AndroidViewModelFactory(requireActivity().getApplication())) + .get(AudioViewModel.class); + + + binding.recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 1)); + adapter = new AudioAdapter(audioDataList, audioViewModel, requireContext(), requireActivity(), 1); + binding.recyclerView.setAdapter(adapter); + + AudioItemCallback callback = new AudioItemCallback(this); + ItemTouchHelper itemTouchHelper = new ItemTouchHelper(callback); + itemTouchHelper.attachToRecyclerView(binding.recyclerView); + } + + private void initEvent() { + binding.add.setOnClickListener(v -> showCustomBottomSheetDialog()); + loadExternal(); + } + + private void loadExternal() { + audioViewModel + .getExternal() + .observe(getViewLifecycleOwner(), new Observer>() { + @Override + public void onChanged(List dataList) { + ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) binding.add.getLayoutParams(); + if (dataList.isEmpty()) { + binding.audioBackground.setVisibility(View.VISIBLE); + + layoutParams.topToBottom = ConstraintLayout.LayoutParams.UNSET; + layoutParams.bottomToTop = ConstraintLayout.LayoutParams.UNSET; + layoutParams.topToTop = ConstraintLayout.LayoutParams.PARENT_ID; + } else { + binding.audioBackground.setVisibility(View.GONE); + + layoutParams.topToTop = ConstraintLayout.LayoutParams.UNSET; + layoutParams.bottomToTop = ConstraintLayout.LayoutParams.UNSET; + layoutParams.topToBottom = R.id.recycler_view; + } + layoutParams.bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID; + layoutParams.startToStart = ConstraintLayout.LayoutParams.PARENT_ID; + layoutParams.endToEnd = ConstraintLayout.LayoutParams.PARENT_ID; + audioDataList = dataList; + adapter.updateData(dataList); + } + }); + } + + private void showCustomBottomSheetDialog() { + BottomSheetDialog bottomSheetDialog = new BottomSheetDialog(requireContext()); + View dialogView = LayoutInflater.from(requireContext()).inflate(R.layout.bottom_dialog, null); + + bottomSheetDialog.setCanceledOnTouchOutside(false); + + dialogView.findViewById(R.id.import_audio).setOnClickListener(v -> { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + openAudioPicker(); + } else { + if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.READ_EXTERNAL_STORAGE) + != PackageManager.PERMISSION_GRANTED) { + ActivityCompat.requestPermissions(requireActivity(), + new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, + REQUEST_CODE_READ_MEDIA_AUDIO); + } else { + openAudioPicker(); + } + } + bottomSheetDialog.dismiss(); + }); + + dialogView.findViewById(R.id.create).setOnClickListener(v -> { + Intent intent = new Intent(getActivity(), RecordAudioActivity.class); + startActivity(intent); + bottomSheetDialog.dismiss(); + }); + + dialogView.findViewById(R.id.cancel_button).setOnClickListener(v -> { + bottomSheetDialog.dismiss(); + }); + + bottomSheetDialog.setContentView(dialogView); + bottomSheetDialog.show(); + } + + private void openAudioPicker() { + Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); + intent.setType("audio/*"); + intent.addCategory(Intent.CATEGORY_OPENABLE); + startActivityForResult(intent, REQUEST_CODE_PICK_AUDIO); + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (requestCode == REQUEST_CODE_READ_MEDIA_AUDIO) { + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + openAudioPicker(); + } else { + Toast.makeText(requireContext(), "Permission denied", Toast.LENGTH_SHORT).show(); + } + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + + if (requestCode != REQUEST_CODE_PICK_AUDIO || resultCode != RESULT_OK || data == null) { + return; + } + + audioUri = data.getData(); + if (audioUri == null) { + Toast.makeText(requireContext(), "The file could not be found.", Toast.LENGTH_LONG).show(); + return; + } + + fileName = AudioUtils.getFileName(audioUri, requireActivity()); + + try { + audioViewModel.getCountAsync(audioUri.toString(), new AudioRepository.CountCallback() { + @Override + public void onCountFetched(int count) { + if (count > 0) { + Toast.makeText(requireContext(), "This file has been imported and cannot be imported again", Toast.LENGTH_LONG).show(); + } else { + audioViewModel.insert(new AudioData(fileName, audioUri.toString(), fileName, audioUri.toString(), "", false, true)); + } + } + }); + } catch (Exception e) { + e.printStackTrace(); + Toast.makeText(requireContext(), "Failed to insert database: " + e.getMessage(), Toast.LENGTH_LONG).show(); + } + } + + @Override + public void onItemSwiped(int position) { + deleteItem(position); + } + + public void deleteItem(int position) { + AudioData audioData = audioDataList.get(position); + try { + audioViewModel.delete(audioData); + Toast.makeText(getContext(), "Audio deleted successfully.", Toast.LENGTH_SHORT).show(); + } catch (Exception e) { + Toast.makeText(getContext(), "Failed to delete audio.", Toast.LENGTH_SHORT).show(); + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + binding = null; } } \ No newline at end of file diff --git a/app/src/main/java/com/prank/funnypranksounds/utils/AudioUtils.java b/app/src/main/java/com/prank/funnypranksounds/utils/AudioUtils.java new file mode 100644 index 0000000..1247036 --- /dev/null +++ b/app/src/main/java/com/prank/funnypranksounds/utils/AudioUtils.java @@ -0,0 +1,43 @@ +package com.prank.funnypranksounds.utils; + +import android.app.Activity; +import android.database.Cursor; +import android.net.Uri; +import android.provider.MediaStore; + +import java.util.Locale; +import java.util.Objects; + +public class AudioUtils { + + public static String getFileName(Uri uri, Activity activity) { + String result = null; + if (Objects.equals(uri.getScheme(), "content")) { + try (Cursor cursor = activity.getContentResolver().query(uri, null, null, null, null)) { + if (cursor != null && cursor.moveToFirst()) { + int displayNameIndex = cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME); + if (displayNameIndex != -1) { + result = cursor.getString(displayNameIndex); + } + } + } + } + if (result == null) { + result = uri.getPath(); + assert result != null; + int cut = result.lastIndexOf('/'); + if (cut != -1) { + result = result.substring(cut + 1); + } + } + return result; + } + + public static String formatTime(long elapsedTime) { + int seconds = (int) (elapsedTime / 1000) % 60; + int minutes = (int) ((elapsedTime / (1000 * 60)) % 60); + int hours = (int) ((elapsedTime / (1000 * 60 * 60)) % 24); + return String.format(Locale.getDefault(),"%02d:%02d:%02d", hours, minutes, seconds); + } + +} diff --git a/app/src/main/java/com/prank/funnypranksounds/utils/JsonParser.java b/app/src/main/java/com/prank/funnypranksounds/utils/JsonParser.java index 2e3f132..c6ca1b5 100644 --- a/app/src/main/java/com/prank/funnypranksounds/utils/JsonParser.java +++ b/app/src/main/java/com/prank/funnypranksounds/utils/JsonParser.java @@ -55,7 +55,7 @@ public class JsonParser { String mp3Url = itemObject.getString("mp3Url"); String preUrl = itemObject.getString("preUrl"); - audioDataList.add(new AudioData(name, url, title, mp3Url, preUrl, false)); + audioDataList.add(new AudioData(name, url, title, mp3Url, preUrl, false,false)); } } diff --git a/app/src/main/java/com/prank/funnypranksounds/viewmodel/AudioViewModel.java b/app/src/main/java/com/prank/funnypranksounds/viewmodel/AudioViewModel.java index 5974d77..8e0ff53 100644 --- a/app/src/main/java/com/prank/funnypranksounds/viewmodel/AudioViewModel.java +++ b/app/src/main/java/com/prank/funnypranksounds/viewmodel/AudioViewModel.java @@ -20,6 +20,10 @@ public class AudioViewModel extends AndroidViewModel { audioRepository = new AudioRepository(application); } + public void insert(AudioData audioData) { + audioRepository.insert(audioData); + } + public void update(AudioData audioData) { audioRepository.update(audioData); } @@ -43,4 +47,16 @@ public class AudioViewModel extends AndroidViewModel { return isFavorite; } + public void getCountAsync(String uri, AudioRepository.CountCallback callback) { + audioRepository.getCountAsync(uri, callback); + } + + public LiveData> getExternal() { + return audioRepository.getExternal(); + } + + public void delete(AudioData audioData){ + audioRepository.delete(audioData); + } + } diff --git a/app/src/main/res/drawable/add.xml b/app/src/main/res/drawable/add.xml new file mode 100644 index 0000000..a6a7aaa --- /dev/null +++ b/app/src/main/res/drawable/add.xml @@ -0,0 +1,33 @@ + + + + + + diff --git a/app/src/main/res/drawable/audio.xml b/app/src/main/res/drawable/audio.xml index adce736..3e5606b 100644 --- a/app/src/main/res/drawable/audio.xml +++ b/app/src/main/res/drawable/audio.xml @@ -8,20 +8,20 @@ android:strokeLineJoin="round" android:strokeWidth="4" android:fillColor="#00000000" - android:strokeColor="#333" + android:strokeColor="#FFEB3B" android:strokeLineCap="round"/> diff --git a/app/src/main/res/drawable/back.xml b/app/src/main/res/drawable/back.xml index a18673e..488c864 100644 --- a/app/src/main/res/drawable/back.xml +++ b/app/src/main/res/drawable/back.xml @@ -1,6 +1,6 @@ + android:strokeColor="#FFEB3B"/> + android:strokeColor="#FFEB3B"/> + android:strokeColor="#FFEB3B"/> + android:strokeColor="#FFEB3B"/> diff --git a/app/src/main/res/drawable/close.xml b/app/src/main/res/drawable/close.xml new file mode 100644 index 0000000..2278091 --- /dev/null +++ b/app/src/main/res/drawable/close.xml @@ -0,0 +1,20 @@ + + + + diff --git a/app/src/main/res/drawable/collection.xml b/app/src/main/res/drawable/collection.xml index c127423..fcd5973 100644 --- a/app/src/main/res/drawable/collection.xml +++ b/app/src/main/res/drawable/collection.xml @@ -8,20 +8,20 @@ android:strokeLineJoin="round" android:strokeWidth="4" android:fillColor="#00000000" - android:strokeColor="#333" + android:strokeColor="#FFEB3B" android:strokeLineCap="round"/> diff --git a/app/src/main/res/drawable/loop.xml b/app/src/main/res/drawable/loop.xml index 9ded698..82a241f 100644 --- a/app/src/main/res/drawable/loop.xml +++ b/app/src/main/res/drawable/loop.xml @@ -8,27 +8,27 @@ android:strokeLineJoin="round" android:strokeWidth="4" android:fillColor="#00000000" - android:strokeColor="#1976D2" + android:strokeColor="#FFEB3B" android:strokeLineCap="round"/> diff --git a/app/src/main/res/drawable/pause.xml b/app/src/main/res/drawable/pause.xml index 0f2938d..8efc01d 100644 --- a/app/src/main/res/drawable/pause.xml +++ b/app/src/main/res/drawable/pause.xml @@ -8,19 +8,19 @@ android:strokeLineJoin="round" android:strokeWidth="2" android:fillColor="#00000000" - android:strokeColor="#333"/> + android:strokeColor="#FFFFFF"/> diff --git a/app/src/main/res/drawable/play.xml b/app/src/main/res/drawable/play.xml index 26fe96c..b92c0e6 100644 --- a/app/src/main/res/drawable/play.xml +++ b/app/src/main/res/drawable/play.xml @@ -8,11 +8,11 @@ android:strokeLineJoin="round" android:strokeWidth="2" android:fillColor="#00000000" - android:strokeColor="#333"/> + android:strokeColor="#FFFFFF"/> + android:strokeColor="#FFFFFF"/> diff --git a/app/src/main/res/drawable/round_edit_text.xml b/app/src/main/res/drawable/round_edit_text.xml new file mode 100644 index 0000000..a512046 --- /dev/null +++ b/app/src/main/res/drawable/round_edit_text.xml @@ -0,0 +1,8 @@ + + + + + + diff --git a/app/src/main/res/drawable/rounded_rectangle_gradient.xml b/app/src/main/res/drawable/rounded_rectangle_tab.xml similarity index 75% rename from app/src/main/res/drawable/rounded_rectangle_gradient.xml rename to app/src/main/res/drawable/rounded_rectangle_tab.xml index ef2ec29..1d906b4 100644 --- a/app/src/main/res/drawable/rounded_rectangle_gradient.xml +++ b/app/src/main/res/drawable/rounded_rectangle_tab.xml @@ -1,10 +1,9 @@ - diff --git a/app/src/main/res/drawable/rounded_rectangle_title.xml b/app/src/main/res/drawable/rounded_rectangle_title.xml new file mode 100644 index 0000000..fd48fdf --- /dev/null +++ b/app/src/main/res/drawable/rounded_rectangle_title.xml @@ -0,0 +1,9 @@ + + + + diff --git a/app/src/main/res/drawable/save.xml b/app/src/main/res/drawable/save.xml new file mode 100644 index 0000000..7016019 --- /dev/null +++ b/app/src/main/res/drawable/save.xml @@ -0,0 +1,30 @@ + + + + + + diff --git a/app/src/main/res/drawable/un_audio.xml b/app/src/main/res/drawable/un_audio.xml index adce736..08946ad 100644 --- a/app/src/main/res/drawable/un_audio.xml +++ b/app/src/main/res/drawable/un_audio.xml @@ -8,20 +8,20 @@ android:strokeLineJoin="round" android:strokeWidth="4" android:fillColor="#00000000" - android:strokeColor="#333" + android:strokeColor="#757575" android:strokeLineCap="round"/> diff --git a/app/src/main/res/drawable/un_category.xml b/app/src/main/res/drawable/un_category.xml index a8b409b..1bf9637 100644 --- a/app/src/main/res/drawable/un_category.xml +++ b/app/src/main/res/drawable/un_category.xml @@ -1,4 +1,30 @@ - - - - \ No newline at end of file + + + + + + diff --git a/app/src/main/res/drawable/un_collection.xml b/app/src/main/res/drawable/un_collection.xml index a8b409b..d1afae3 100644 --- a/app/src/main/res/drawable/un_collection.xml +++ b/app/src/main/res/drawable/un_collection.xml @@ -1,4 +1,27 @@ - - - - \ No newline at end of file + + + + + diff --git a/app/src/main/res/drawable/voice.xml b/app/src/main/res/drawable/voice.xml new file mode 100644 index 0000000..9eafe11 --- /dev/null +++ b/app/src/main/res/drawable/voice.xml @@ -0,0 +1,26 @@ + + + + + diff --git a/app/src/main/res/layout/activity_audio_player.xml b/app/src/main/res/layout/activity_audio_player.xml index 1689edd..36e30ad 100644 --- a/app/src/main/res/layout/activity_audio_player.xml +++ b/app/src/main/res/layout/activity_audio_player.xml @@ -22,7 +22,7 @@ android:layout_marginTop="75dp" android:layout_marginEnd="50dp" android:layout_marginBottom="75dp" - android:background="@drawable/rounded_rectangle_gradient" + android:background="@drawable/rounded_rectangle_tab" app:layout_constraintBottom_toTopOf="@id/seek_bar" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" @@ -73,8 +73,10 @@ android:layout_height="wrap_content" android:text="@string/app_name" android:textColor="@color/black" - android:textSize="18sp" + android:textSize="24sp" android:textStyle="bold" + android:maxLines="1" + android:ellipsize="end" app:layout_constraintBottom_toBottomOf="@+id/back" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" @@ -122,7 +124,7 @@ android:id="@+id/play" android:layout_width="80dp" android:layout_height="80dp" - android:background="@drawable/rounded_rectangle_gradient" + android:background="@drawable/rounded_rectangle_tab" android:padding="10dp" android:src="@drawable/play" app:layout_constraintBottom_toBottomOf="parent" diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index e1263c4..f5189c4 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -12,7 +12,7 @@ android:id="@+id/setting" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginStart="24dp" + android:layout_marginStart="16dp" android:src="@drawable/setting" app:layout_constraintBottom_toBottomOf="@+id/title" app:layout_constraintStart_toStartOf="parent" diff --git a/app/src/main/res/layout/activity_record_audio.xml b/app/src/main/res/layout/activity_record_audio.xml new file mode 100644 index 0000000..945b46b --- /dev/null +++ b/app/src/main/res/layout/activity_record_audio.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_save_audio.xml b/app/src/main/res/layout/activity_save_audio.xml new file mode 100644 index 0000000..2361c50 --- /dev/null +++ b/app/src/main/res/layout/activity_save_audio.xml @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_setting.xml b/app/src/main/res/layout/activity_setting.xml index e663ada..71deb56 100644 --- a/app/src/main/res/layout/activity_setting.xml +++ b/app/src/main/res/layout/activity_setting.xml @@ -1,5 +1,6 @@ - + android:layout_marginStart="16dp" + android:src="@drawable/back" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> - + android:textStyle="bold" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml index 67def30..e9ea9ea 100644 --- a/app/src/main/res/layout/activity_splash.xml +++ b/app/src/main/res/layout/activity_splash.xml @@ -9,8 +9,8 @@ + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_audio.xml b/app/src/main/res/layout/fragment_audio.xml index 148decd..e95223a 100644 --- a/app/src/main/res/layout/fragment_audio.xml +++ b/app/src/main/res/layout/fragment_audio.xml @@ -1,14 +1,73 @@ - - - + android:layout_height="wrap_content" + android:layout_marginStart="50dp" + android:layout_marginTop="10dp" + android:layout_marginEnd="50dp" + android:layout_marginBottom="10dp" + android:background="@drawable/rounded_rectangle_tab" + android:gravity="center" + android:orientation="horizontal" + android:paddingStart="16dp" + android:paddingTop="5dp" + android:paddingEnd="16dp" + android:paddingBottom="5dp" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent"> - \ No newline at end of file + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_audio.xml b/app/src/main/res/layout/item_audio.xml index 9fed9cc..b6597e8 100644 --- a/app/src/main/res/layout/item_audio.xml +++ b/app/src/main/res/layout/item_audio.xml @@ -1,9 +1,10 @@ + android:background="@drawable/rounded_rectangle_tab"> - - - - \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..0c2c2f2 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp deleted file mode 100644 index 4564878..0000000 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-hdpi/import_audio.png b/app/src/main/res/mipmap-hdpi/import_audio.png new file mode 100644 index 0000000..fce4528 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/import_audio.png differ diff --git a/app/src/main/res/mipmap-hdpi/record_sound.png b/app/src/main/res/mipmap-hdpi/record_sound.png new file mode 100644 index 0000000..5563715 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/record_sound.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..d511f05 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp deleted file mode 100644 index 6123f68..0000000 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..4e9c6bc Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp deleted file mode 100644 index e17079e..0000000 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..0a7236f Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp deleted file mode 100644 index 23e0da2..0000000 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..fa3cdb7 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp deleted file mode 100644 index 78cf27d..0000000 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp and /dev/null differ diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 741c559..438ab80 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -3,4 +3,13 @@ #FF000000 #FFFFFFFF #757575 + #505BC8 + #FFEB3B + #D8A7FF + #A0FFFC + #F0C259 + #A6F2F2 + #FF9BCE + #A3E1A3 + #B2B6FF \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c0156f2..6fc1d72 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -3,6 +3,15 @@ Hello blank fragment Setting + Category + Audio + Collection Version Share + Oops! Looks like there’s no audio here yet.\n 🎧 Please add some fun sounds! 🎶 + Record Audio + 00:00:00 + Please enter a name for your recording + Add Audio + Save Audio \ No newline at end of file diff --git a/keystore.properties b/keystore.properties new file mode 100644 index 0000000..2a02716 --- /dev/null +++ b/keystore.properties @@ -0,0 +1,6 @@ +app_name=Funny Prank Sounds +package_name=keystore.properties +keystoreFile=app/FunnyPrankSounds.jks +key_alias=FunnyPrankSoundskey0 +key_store_password=FunnyPrankSounds +key_password=FunnyPrankSounds \ No newline at end of file