创建仓库

This commit is contained in:
lihongwei 2024-12-23 17:18:13 +08:00
commit e2bf38525b
95 changed files with 6866 additions and 0 deletions

15
.gitignore vendored Normal file
View File

@ -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

1
app/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

56
app/build.gradle.kts Normal file
View File

@ -0,0 +1,56 @@
import java.text.SimpleDateFormat
import java.util.Date
plugins {
alias(libs.plugins.android.application)
}
val timestamp = SimpleDateFormat("MM_dd_HH_mm").format(Date())
android {
namespace = "com.prank.funnypranksounds"
compileSdk = 34
defaultConfig {
applicationId = "com.prank.funnypranksounds"
minSdk = 23
targetSdk = 34
versionCode = 1
versionName = "1.0.0"
setProperty("archivesBaseName", "Funny Prank Sounds" + versionName + "(${versionCode})_$timestamp")
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildFeatures {
viewBinding = true
}
buildTypes {
release {
isMinifyEnabled = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}
dependencies {
implementation(libs.appcompat)
implementation(libs.material)
implementation(libs.activity)
implementation(libs.constraintlayout)
testImplementation(libs.junit)
androidTestImplementation(libs.ext.junit)
androidTestImplementation(libs.espresso.core)
implementation("com.github.bumptech.glide:glide:4.16.0")
annotationProcessor("com.github.bumptech.glide:compiler:4.16.0")
implementation ("androidx.room:room-runtime:2.6.1")
annotationProcessor ("androidx.room:room-compiler:2.6.1")
}

21
app/proguard-rules.pro vendored Normal file
View File

@ -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

View File

@ -0,0 +1,26 @@
package com.prank.funnypranksounds;
import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("com.prank.funnypranksounds", appContext.getPackageName());
}
}

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
<application
android:name=".MyApplication"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.FunnyPrankSounds"
tools:targetApi="31">
<activity
android:name=".ui.activity.AudioPlayerActivity"
android:exported="false" />
<activity
android:name=".ui.activity.CategoryActivity"
android:exported="false" />
<activity
android:name=".ui.activity.SettingActivity"
android:exported="false" />
<activity
android:name=".ui.activity.MainActivity"
android:exported="false" />
<activity
android:name=".ui.activity.SplashActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 598 KiB

View File

@ -0,0 +1,48 @@
package com.prank.funnypranksounds;
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
import com.prank.funnypranksounds.data.local.entity.AudioData;
import com.prank.funnypranksounds.data.repository.AudioRepository;
import com.prank.funnypranksounds.utils.JsonParser;
import java.util.ArrayList;
import java.util.List;
public class MyApplication extends Application {
public static MyApplication myApplication;
public static final String Database_Name = "Database";
public static final int Database_Version = 1;
private static final String PREF_NAME = "preferences";
private static final String KEY_INITIALIZED = "initDatabase";
@Override
public void onCreate() {
super.onCreate();
myApplication = this;
SharedPreferences preferences = getSharedPreferences(PREF_NAME, MODE_PRIVATE);
boolean init = preferences.getBoolean(KEY_INITIALIZED, false);
if (!init) {
initDatabase();
preferences.edit().putBoolean(KEY_INITIALIZED, true).apply();
}
}
private void initDatabase() {
AudioRepository imageRepository = new AudioRepository(getContext());
List<AudioData> audioDataList = JsonParser.parseJson("prank.json");
Log.d("appliacation", "data: " + audioDataList);
imageRepository.insertAll(audioDataList);
}
public static Context getContext() {
return myApplication.getApplicationContext();
}
}

View File

@ -0,0 +1,30 @@
package com.prank.funnypranksounds.data.local.dao;
import androidx.lifecycle.LiveData;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.Query;
import androidx.room.Update;
import com.prank.funnypranksounds.data.local.entity.AudioData;
import java.util.List;
@Dao
public interface AudioDataDao {
@Insert
void insertAll(List<AudioData> audioDataList);
@Update
void update(AudioData audioData);
@Query("SELECT * FROM AudioData WHERE id IN (SELECT MIN(id) FROM AudioData GROUP BY categoryName)")
LiveData<List<AudioData>> getFirstCategory();
@Query("SELECT * FROM AudioData WHERE categoryName = :name")
LiveData<List<AudioData>> getCategory(String name);
@Query("SELECT * FROM AudioData WHERE isFavorite = 1")
LiveData<List<AudioData>> getFavorite();
}

View File

@ -0,0 +1,32 @@
package com.prank.funnypranksounds.data.local.database;
import android.content.Context;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import com.prank.funnypranksounds.MyApplication;
import com.prank.funnypranksounds.data.local.dao.AudioDataDao;
import com.prank.funnypranksounds.data.local.entity.AudioData;
@Database(entities = {AudioData.class}, version = MyApplication.Database_Version, exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {
public abstract AudioDataDao audioDataDao();
private static volatile AppDatabase INSTANCE;
public static AppDatabase getInstance(Context context) {
if (INSTANCE == null) {
synchronized (AppDatabase.class) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
AppDatabase.class, MyApplication.Database_Name)
.build();
}
}
}
return INSTANCE;
}
}

View File

@ -0,0 +1,84 @@
package com.prank.funnypranksounds.data.local.entity;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
import java.io.Serializable;
@Entity
public class AudioData implements Serializable {
@PrimaryKey(autoGenerate = true)
private int id;
private String categoryName;
private String categoryUrl;
private String title;
private String mp3Url;
private String preUrl;
private boolean isFavorite;
public AudioData(String categoryName, String categoryUrl, String title, String mp3Url, String preUrl, boolean isFavorite) {
this.categoryName = categoryName;
this.categoryUrl = categoryUrl;
this.title = title;
this.mp3Url = mp3Url;
this.preUrl = preUrl;
this.isFavorite = isFavorite;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCategoryName() {
return categoryName;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
public String getCategoryUrl() {
return categoryUrl;
}
public void setCategoryUrl(String categoryUrl) {
this.categoryUrl = categoryUrl;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getMp3Url() {
return mp3Url;
}
public void setMp3Url(String mp3Url) {
this.mp3Url = mp3Url;
}
public String getPreUrl() {
return preUrl;
}
public void setPreUrl(String preUrl) {
this.preUrl = preUrl;
}
public boolean isFavorite() {
return isFavorite;
}
public void setFavorite(boolean favorite) {
isFavorite = favorite;
}
}

View File

@ -0,0 +1,42 @@
package com.prank.funnypranksounds.data.repository;
import android.content.Context;
import androidx.lifecycle.LiveData;
import com.prank.funnypranksounds.data.local.dao.AudioDataDao;
import com.prank.funnypranksounds.data.local.database.AppDatabase;
import com.prank.funnypranksounds.data.local.entity.AudioData;
import java.util.List;
public class AudioRepository {
private final AudioDataDao dao;
public AudioRepository(Context context) {
AppDatabase appDatabase = AppDatabase.getInstance(context);
dao = appDatabase.audioDataDao();
}
public void insertAll(List<AudioData> audioDataList) {
new Thread(() -> dao.insertAll(audioDataList)).start();
}
public void update(AudioData audioData) {
new Thread(() -> dao.update(audioData)).start();
}
public LiveData<List<AudioData>> getFirstCategory() {
return dao.getFirstCategory();
}
public LiveData<List<AudioData>> getCategory(String name) {
return dao.getCategory(name);
}
public LiveData<List<AudioData>> getFavorite() {
return dao.getFavorite();
}
}

View File

@ -0,0 +1,230 @@
package com.prank.funnypranksounds.ui.activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.SeekBar;
import android.widget.Toast;
import androidx.activity.EdgeToEdge;
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.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.prank.funnypranksounds.R;
import com.prank.funnypranksounds.data.local.entity.AudioData;
import com.prank.funnypranksounds.databinding.ActivityAudioPlayerBinding;
import com.prank.funnypranksounds.viewmodel.AudioViewModel;
import java.io.IOException;
import java.util.Objects;
public class AudioPlayerActivity extends AppCompatActivity {
private ActivityAudioPlayerBinding binding;
private MediaPlayer mediaPlayer;
private AudioManager audioManager;
private int maxVolume, currentVolume;
private boolean isPlaying = false;
private boolean isLooping = false;
private AudioData audioData;
private AudioViewModel audioViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityAudioPlayerBinding.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() {
audioData = (AudioData) getIntent().getSerializableExtra("audioData");
if (audioData == null) {
finish();
return;
}
audioViewModel = new ViewModelProvider(this, new ViewModelProvider.AndroidViewModelFactory(getApplication()))
.get(AudioViewModel.class);
IntentFilter filter = new IntentFilter("android.media.VOLUME_CHANGED_ACTION");
registerReceiver(volumeReceiver, filter);
audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
}
private void initEvent() {
binding.title.setText(audioData.getTitle());
binding.back.setOnClickListener(v -> finish());
binding.favorite.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
updateFavorite(audioData);
}
});
binding.loop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
isLooping = !isLooping;
binding.loop.setImageResource(isLooping ? R.drawable.loop : R.drawable.un_loop);
if (mediaPlayer != null) {
mediaPlayer.setLooping(isLooping);
}
}
});
binding.play.setOnClickListener(v -> playAudio());
binding.seekBar.setMax(maxVolume);
binding.seekBar.setProgress(currentVolume);
binding.seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, progress, 0);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
loadImage();
loadIsFavorite(audioData);
}
private void loadIsFavorite(AudioData audioData) {
boolean isFavorite = audioData.isFavorite();
updateFavoriteIcon(isFavorite);
}
private void loadImage() {
Glide.with(this)
.load(audioData.getPreUrl())
.placeholder(R.mipmap.placeholder)
.error(R.mipmap.placeholder)
.transform(new RoundedCorners(16))
.into(binding.image);
}
private final BroadcastReceiver volumeReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (Objects.equals(intent.getAction(), "android.media.VOLUME_CHANGED_ACTION")) {
int currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
binding.seekBar.setProgress(currentVolume);
}
}
};
private void updateFavorite(AudioData audioData) {
boolean isFavorite = audioViewModel.toggleFavorite(audioData);
updateFavoriteIcon(isFavorite);
}
private void updateFavoriteIcon(boolean isFavorite) {
binding.favorite.setImageResource(isFavorite ? R.drawable.like : R.drawable.un_like);
}
private void playAudio() {
String audioUrl = audioData.getMp3Url();
if (mediaPlayer == null) {
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
if (audioUrl.startsWith("content://")) {
Uri audioUri = Uri.parse(audioUrl);
mediaPlayer.setDataSource(this, audioUri);
} else {
mediaPlayer.setDataSource(audioUrl);
}
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mediaPlayer.start();
binding.play.setImageResource(R.drawable.pause);
isPlaying = true;
mediaPlayer.setLooping(isLooping);
}
});
mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Toast.makeText(AudioPlayerActivity.this, "Error playing audio", Toast.LENGTH_SHORT).show();
return false;
}
});
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
if (!isLooping) {
binding.play.setImageResource(R.drawable.play);
isPlaying = false;
}
}
});
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(AudioPlayerActivity.this, "Error setting data source", Toast.LENGTH_SHORT).show();
}
} else {
if (isPlaying) {
mediaPlayer.pause();
binding.play.setImageResource(R.drawable.play);
} else {
mediaPlayer.start();
binding.play.setImageResource(R.drawable.pause);
}
isPlaying = !isPlaying;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(volumeReceiver);
if (mediaPlayer != null) {
mediaPlayer.release();
mediaPlayer = null;
}
binding = null;
}
}

View File

@ -0,0 +1,95 @@
package com.prank.funnypranksounds.ui.activity;
import android.os.Bundle;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.GridLayoutManager;
import com.prank.funnypranksounds.R;
import com.prank.funnypranksounds.data.local.entity.AudioData;
import com.prank.funnypranksounds.databinding.ActivityCategoryBinding;
import com.prank.funnypranksounds.ui.adapter.AudioAdapter;
import com.prank.funnypranksounds.utils.ItemDecoration;
import com.prank.funnypranksounds.viewmodel.AudioViewModel;
import java.util.ArrayList;
import java.util.List;
public class CategoryActivity extends AppCompatActivity {
private ActivityCategoryBinding binding;
private AudioViewModel audioViewModel;
private AudioAdapter adapter;
private String name;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityCategoryBinding.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() {
name = getIntent().getStringExtra("name");
if (name == null) {
finish();
return;
}
audioViewModel = new ViewModelProvider(this,
new ViewModelProvider.AndroidViewModelFactory(getApplication()))
.get(AudioViewModel.class);
binding.recyclerView.setLayoutManager(new GridLayoutManager(this, 2));
adapter = new AudioAdapter(new ArrayList<>(), audioViewModel, this, this, 1);
binding.recyclerView.setAdapter(adapter);
ItemDecoration itemDecoration = new ItemDecoration(16, 19, 10);
binding.recyclerView.addItemDecoration(itemDecoration);
}
private void initEvent() {
binding.title.setText(name);
binding.back.setOnClickListener(v -> finish());
loadCategory();
}
private void loadCategory() {
audioViewModel
.getCategory(name)
.observe(this, new Observer<List<AudioData>>() {
@Override
public void onChanged(List<AudioData> audioDataList) {
adapter.updateData(audioDataList);
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
binding = null;
}
}

View File

@ -0,0 +1,139 @@
package com.prank.funnypranksounds.ui.activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import com.prank.funnypranksounds.R;
import com.prank.funnypranksounds.databinding.ActivityMainBinding;
import com.prank.funnypranksounds.databinding.TabCustomBinding;
import com.prank.funnypranksounds.ui.adapter.MainAdapter;
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.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() {
MainAdapter adapter = new MainAdapter(this);
binding.viewpager.setAdapter(adapter);
}
private void initEvent() {
binding.viewpager.setUserInputEnabled(false);
binding.setting.setOnClickListener(v -> {
Intent intent = new Intent(this, SettingActivity.class);
this.startActivity(intent);
});
new TabLayoutMediator(binding.tabLayout, binding.viewpager, (tab, position) -> {
TabCustomBinding tabCustomBinding = TabCustomBinding.inflate(LayoutInflater.from(this));
tab.setCustomView(tabCustomBinding.getRoot());
setTab(tabCustomBinding, position);
}).attach();
binding.tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
updateTab(tab, true);
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
updateTab(tab, false);
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
private void updateTab(TabLayout.Tab tab, boolean isSelected) {
if (tab.getCustomView() != null) {
TabCustomBinding tabBinding = TabCustomBinding.bind(tab.getCustomView());
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);
tabBinding.text.setTextColor(textColor);
}
}
private int getIconResource(int position, boolean isSelected) {
switch (position) {
case 1:
if (isSelected) {
return R.drawable.audio;
}
return R.drawable.un_audio;
case 2:
if (isSelected) {
return R.drawable.collection;
}
return R.drawable.un_collection;
default:
if (isSelected) {
return R.drawable.category;
}
return R.drawable.un_category;
}
}
});
}
private void setTab(TabCustomBinding tabCustomBinding, int position) {
switch (position) {
case 0:
tabCustomBinding.imageView.setImageResource(R.drawable.category);
tabCustomBinding.text.setText("Category");
tabCustomBinding.text.setTextColor(getResources().getColor(R.color.black, null));
break;
case 1:
tabCustomBinding.imageView.setImageResource(R.drawable.audio);
tabCustomBinding.text.setText("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.setTextColor(getResources().getColor(R.color.gray, null));
break;
}
}
@Override
public void onDestroy() {
super.onDestroy();
binding = null;
}
}

View File

@ -0,0 +1,48 @@
package com.prank.funnypranksounds.ui.activity;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import com.prank.funnypranksounds.databinding.ActivitySettingBinding;
import com.prank.funnypranksounds.utils.SettingUtils;
public class SettingActivity extends AppCompatActivity {
private ActivitySettingBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivitySettingBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
initData();
initEvent();
}
private void initData() {
}
private void initEvent() {
binding.back.setOnClickListener(v -> finish());
binding.version.setText(SettingUtils.getCurrentVersion(this));
binding.share.setOnClickListener(v -> {
SettingUtils.shareApp(this);
});
}
@Override
protected void onDestroy() {
super.onDestroy();
binding = null;
}
}

View File

@ -0,0 +1,76 @@
package com.prank.funnypranksounds.ui.activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.CountDownTimer;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.prank.funnypranksounds.R;
import com.prank.funnypranksounds.databinding.ActivitySplashBinding;
public class SplashActivity extends AppCompatActivity {
private ActivitySplashBinding binding;
private static final long TOTAL_TIME = 1000;
private CountDownTimer countDownTimer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivitySplashBinding.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;
});
Glide.with(this)
.load(R.mipmap.ic_launcher)
.transform(new RoundedCorners(16))
.into(binding.image);
countDownTimer = new CountDownTimer(TOTAL_TIME, 100) {
@Override
public void onTick(long millisUntilFinished) {
int percentage = (int) (100 - (float) millisUntilFinished / TOTAL_TIME * 100);
binding.progress.setProgress(percentage);
}
@Override
public void onFinish() {
startMain();
}
};
countDownTimer.start();
}
private void startMain() {
binding.progress.setProgress(100);
Intent intent = new Intent(SplashActivity.this, MainActivity.class);
startActivity(intent);
finish();
}
@Override
protected void onDestroy() {
super.onDestroy();
if (countDownTimer != null) {
countDownTimer.cancel();
}
binding = null;
}
}

View File

@ -0,0 +1,142 @@
package com.prank.funnypranksounds.ui.adapter;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.prank.funnypranksounds.R;
import com.prank.funnypranksounds.data.local.entity.AudioData;
import com.prank.funnypranksounds.ui.activity.AudioPlayerActivity;
import com.prank.funnypranksounds.ui.activity.CategoryActivity;
import com.prank.funnypranksounds.viewmodel.AudioViewModel;
import java.util.List;
public class AudioAdapter extends RecyclerView.Adapter<AudioAdapter.ViewHolder> {
private List<AudioData> audioDataList;
private AudioViewModel audioViewModel;
private final Context context;
private final Activity activity;
private final int type;
public AudioAdapter(List<AudioData> audioDataList, AudioViewModel audioViewModel, Context context, Activity activity, int type) {
this.context = context;
this.audioViewModel = audioViewModel;
this.audioDataList = audioDataList;
this.activity = activity;
this.type = type;
}
public void updateData(List<AudioData> newAudioDataList) {
this.audioDataList = newAudioDataList;
notifyDataSetChanged();
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.item_audio, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
AudioData audioData = audioDataList.get(position);
String name = "";
if (type == 0) {
name = audioData.getCategoryName();
} else if (type == 1) {
name = audioData.getTitle();
}
holder.bind(audioData, name);
}
@Override
public int getItemCount() {
return audioDataList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
ImageView like;
TextView textView;
ViewHolder(View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.imageView);
like = itemView.findViewById(R.id.like);
textView = itemView.findViewById(R.id.textView);
}
void bind(AudioData audioData, String name) {
String audioDataImagePath = audioData.getCategoryUrl();
if (type == 0 || type == 1) {
textView.setVisibility(View.VISIBLE);
setItemText(name);
}
loadImage(audioDataImagePath);
setLike(audioData);
setClickListeners(audioData, name);
}
private void loadImage(String imagePath) {
Glide.with(context)
.load(imagePath)
.placeholder(R.mipmap.placeholder)
.error(R.mipmap.placeholder)
.transform(new RoundedCorners(32))
.into(imageView);
}
private void setItemText(String name) {
textView.setText(name);
}
private void setLike(AudioData audioData) {
like.setImageResource(audioData.isFavorite()
? R.drawable.like
: R.drawable.un_like);
}
private void setClickListeners(final AudioData audioData, String name) {
imageView.setOnClickListener(v -> {
Intent intent;
if (type == 0) {
intent = new Intent(context, CategoryActivity.class);
intent.putExtra("name", name);
} else {
intent = new Intent(context, AudioPlayerActivity.class);
intent.putExtra("audioData", audioData);
}
context.startActivity(intent);
});
like.setOnClickListener(v -> toggleFavorite(audioData));
}
private void toggleFavorite(AudioData audioData) {
audioViewModel.update(audioData);
boolean newStatus = !audioData.isFavorite();
audioData.setFavorite(newStatus);
notifyItemChanged(getAdapterPosition());
}
}
}

View File

@ -0,0 +1,37 @@
package com.prank.funnypranksounds.ui.adapter;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import com.prank.funnypranksounds.ui.fragment.AudioFragment;
import com.prank.funnypranksounds.ui.fragment.CategoryFragment;
import com.prank.funnypranksounds.ui.fragment.FavoriteFragment;
import java.util.ArrayList;
import java.util.List;
public class MainAdapter extends FragmentStateAdapter {
private final List<Fragment> fragmentList;
public MainAdapter(@NonNull FragmentActivity fragmentActivity) {
super(fragmentActivity);
fragmentList = new ArrayList<>();
fragmentList.add(new CategoryFragment());
fragmentList.add(new AudioFragment());
fragmentList.add(new FavoriteFragment());
}
@NonNull
@Override
public Fragment createFragment(int position) {
return fragmentList.get(position);
}
@Override
public int getItemCount() {
return fragmentList.size();
}
}

View File

@ -0,0 +1,66 @@
package com.prank.funnypranksounds.ui.fragment;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.prank.funnypranksounds.R;
/**
* A simple {@link Fragment} subclass.
* Use the {@link AudioFragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class AudioFragment extends Fragment {
// 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";
// 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);
}
}
@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);
}
}

View File

@ -0,0 +1,77 @@
package com.prank.funnypranksounds.ui.fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.GridLayoutManager;
import com.prank.funnypranksounds.data.local.entity.AudioData;
import com.prank.funnypranksounds.databinding.FragmentCategoryBinding;
import com.prank.funnypranksounds.ui.adapter.AudioAdapter;
import com.prank.funnypranksounds.utils.ItemDecoration;
import com.prank.funnypranksounds.viewmodel.AudioViewModel;
import java.util.ArrayList;
import java.util.List;
public class CategoryFragment extends Fragment {
private FragmentCategoryBinding binding;
private AudioAdapter adapter;
private AudioViewModel audioViewModel;
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
binding = FragmentCategoryBinding.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(), 2));
adapter = new AudioAdapter(new ArrayList<>(), audioViewModel, requireContext(), requireActivity(), 0);
binding.recyclerView.setAdapter(adapter);
ItemDecoration itemDecoration = new ItemDecoration(16, 19, 10);
binding.recyclerView.addItemDecoration(itemDecoration);
}
private void initEvent() {
loadFirstCategory();
}
private void loadFirstCategory() {
audioViewModel
.getFirstCategory()
.observe(getViewLifecycleOwner(), new Observer<List<AudioData>>() {
@Override
public void onChanged(List<AudioData> audioDataList) {
if (audioDataList != null) {
adapter.updateData(audioDataList);
}
}
});
}
@Override
public void onDestroy() {
super.onDestroy();
binding = null;
}
}

View File

@ -0,0 +1,78 @@
package com.prank.funnypranksounds.ui.fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.GridLayoutManager;
import com.prank.funnypranksounds.data.local.database.AppDatabase;
import com.prank.funnypranksounds.data.local.entity.AudioData;
import com.prank.funnypranksounds.databinding.FragmentFavoriteBinding;
import com.prank.funnypranksounds.ui.adapter.AudioAdapter;
import com.prank.funnypranksounds.utils.ItemDecoration;
import com.prank.funnypranksounds.viewmodel.AudioViewModel;
import java.util.ArrayList;
import java.util.List;
public class FavoriteFragment extends Fragment {
private FragmentFavoriteBinding binding;
private AudioAdapter adapter;
private AudioViewModel audioViewModel;
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
binding = FragmentFavoriteBinding.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(), 3));
adapter = new AudioAdapter(new ArrayList<>(), audioViewModel, requireContext(), requireActivity(), 1);
binding.recyclerView.setAdapter(adapter);
ItemDecoration itemDecoration = new ItemDecoration(16, 19, 10);
binding.recyclerView.addItemDecoration(itemDecoration);
}
private void initEvent(){
loadFavorite();
}
private void loadFavorite() {
audioViewModel
.getFavorite()
.observe(getViewLifecycleOwner(), new Observer<List<AudioData>>() {
@Override
public void onChanged(List<AudioData> audioDataList) {
if (audioDataList != null) {
adapter.updateData(audioDataList);
}
}
});
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}

View File

@ -0,0 +1,76 @@
package com.prank.funnypranksounds.utils;
import android.graphics.Rect;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import com.prank.funnypranksounds.MyApplication;
public class ItemDecoration extends RecyclerView.ItemDecoration {
private final int v;
private final int h;
private final int ex;
public ItemDecoration(int v, int h, int ex) {
this.v = Math.round(dpToPx(v));
this.h = Math.round(dpToPx(h));
this.ex = Math.round(dpToPx(ex));
}
@Override
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
int spanCount = 1;
int spanSize = 1;
int spanIndex = 0;
int childAdapterPosition = parent.getChildAdapterPosition(view);
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof StaggeredGridLayoutManager) {
StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) layoutManager;
StaggeredGridLayoutManager.LayoutParams layoutParams = (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams();
spanCount = staggeredGridLayoutManager.getSpanCount();
if (layoutParams.isFullSpan()) {
spanSize = spanCount;
}
spanIndex = layoutParams.getSpanIndex();
} else if (layoutManager instanceof GridLayoutManager) {
GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
GridLayoutManager.LayoutParams layoutParams = (GridLayoutManager.LayoutParams) view.getLayoutParams();
spanCount = gridLayoutManager.getSpanCount();
spanSize = gridLayoutManager.getSpanSizeLookup().getSpanSize(childAdapterPosition);
spanIndex = layoutParams.getSpanIndex();
} else if (layoutManager instanceof LinearLayoutManager) {
outRect.left = v;
outRect.right = v;
outRect.bottom = h;
}
if (spanSize == spanCount) {
outRect.left = v + ex;
outRect.right = v + ex;
} else {
int itemAllSpacing = (v * (spanCount + 1) + ex * 2) / spanCount;
int left = v * (spanIndex + 1) - itemAllSpacing * spanIndex + ex;
int right = itemAllSpacing - left;
outRect.left = left;
outRect.right = right;
}
outRect.bottom = h;
}
public static float dpToPx(float dpValue) {
float density = MyApplication.getContext().getResources().getDisplayMetrics().density;
return density * dpValue + 0.5f;
}
}

View File

@ -0,0 +1,69 @@
package com.prank.funnypranksounds.utils;
import android.util.Log;
import com.prank.funnypranksounds.MyApplication;
import com.prank.funnypranksounds.data.local.entity.AudioData;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
public class JsonParser {
private static String loadJSONFromAsset(String fileName) {
StringBuilder jsonString = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(MyApplication.getContext().getAssets().open(fileName)))) {
String line;
while ((line = reader.readLine()) != null) {
jsonString.append(line);
}
} catch (IOException e) {
e.printStackTrace();
}
return jsonString.toString();
}
public static List<AudioData> parseJson(String fileName) {
List<AudioData> audioDataList = new ArrayList<>();
try {
String jsonString = loadJSONFromAsset(fileName);
if (jsonString.isEmpty()) {
throw new IllegalArgumentException("JSON file is empty or invalid.");
}
JSONArray jsonArray = new JSONArray(jsonString);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject categoryObject = jsonArray.getJSONObject(i);
String name = categoryObject.getString("categoryName");
String url = categoryObject.getString("categoryUrl");
JSONArray listArray = categoryObject.getJSONArray("list");
for (int j = 0; j < listArray.length(); j++) {
JSONObject itemObject = listArray.getJSONObject(j);
String title = itemObject.getString("title");
String mp3Url = itemObject.getString("mp3Url");
String preUrl = itemObject.getString("preUrl");
audioDataList.add(new AudioData(name, url, title, mp3Url, preUrl, false));
}
}
} catch (Exception e) {
e.printStackTrace();
}
return audioDataList;
}
}

View File

@ -0,0 +1,33 @@
package com.prank.funnypranksounds.utils;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
public class SettingUtils {
public static String getCurrentVersion(Context context) {
try {
PackageManager packageManager = context.getPackageManager();
PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
return packageInfo.versionName;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return null;
}
}
public static void shareApp(Context context) {
String appPackageName = context.getPackageName();
String appName = context.getApplicationInfo().loadLabel(context.getPackageManager()).toString();
String appPlayStoreLink = "https://play.google.com/store/apps/details?id=" + appPackageName;
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_SUBJECT, "Check out this app: " + appName);
shareIntent.putExtra(Intent.EXTRA_TEXT, "Download " + appName + " from Google Play: " + appPlayStoreLink);
context.startActivity(Intent.createChooser(shareIntent, "Share " + appName + " via"));
}
}

View File

@ -0,0 +1,46 @@
package com.prank.funnypranksounds.viewmodel;
import android.app.Application;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import com.prank.funnypranksounds.data.local.entity.AudioData;
import com.prank.funnypranksounds.data.repository.AudioRepository;
import java.util.List;
public class AudioViewModel extends AndroidViewModel {
private final AudioRepository audioRepository;
public AudioViewModel(@NonNull Application application) {
super(application);
audioRepository = new AudioRepository(application);
}
public void update(AudioData audioData) {
audioRepository.update(audioData);
}
public LiveData<List<AudioData>> getFirstCategory() {
return audioRepository.getFirstCategory();
}
public LiveData<List<AudioData>> getCategory(String name) {
return audioRepository.getCategory(name);
}
public LiveData<List<AudioData>> getFavorite() {
return audioRepository.getFavorite();
}
public boolean toggleFavorite(AudioData audioData) {
boolean isFavorite = !audioData.isFavorite();
audioData.setFavorite(isFavorite);
audioRepository.update(audioData);
return isFavorite;
}
}

View File

@ -0,0 +1,30 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

View File

@ -0,0 +1,27 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M8,44V4H31L40,14.5V44H8Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M32,14L26,16.969V31.5"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M20.5,31.5m-5.5,0a5.5,5.5 0,1 1,11 0a5.5,5.5 0,1 1,-11 0"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,20 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M24,36L12,24L24,12"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M36,36L24,24L36,12"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,30 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M18,6H8C6.895,6 6,6.895 6,8V18C6,19.105 6.895,20 8,20H18C19.105,20 20,19.105 20,18V8C20,6.895 19.105,6 18,6Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"/>
<path
android:pathData="M18,28H8C6.895,28 6,28.895 6,30V40C6,41.105 6.895,42 8,42H18C19.105,42 20,41.105 20,40V30C20,28.895 19.105,28 18,28Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"/>
<path
android:pathData="M40,6H30C28.895,6 28,6.895 28,8V18C28,19.105 28.895,20 30,20H40C41.105,20 42,19.105 42,18V8C42,6.895 41.105,6 40,6Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"/>
<path
android:pathData="M40,28H30C28.895,28 28,28.895 28,30V40C28,41.105 28.895,42 30,42H40C41.105,42 42,41.105 42,40V30C42,28.895 41.105,28 40,28Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"/>
</vector>

View File

@ -0,0 +1,27 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M40,23V14L31,4H10C8.895,4 8,4.895 8,6V42C8,43.105 8.895,44 10,44H22"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M30.85,30C28.724,30 27,32.009 27,34.486C27,38.973 31.55,43.051 34,44C36.45,43.051 41,38.973 41,34.486C41,32.009 39.276,30 37.15,30C35.848,30 34.697,30.753 34,31.906C33.303,30.753 32.152,30 30.85,30Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M30,4V14H40"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,19 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M24,6V42C17,42 11.799,32.839 11.799,32.839H6C4.895,32.839 4,31.944 4,30.839V17.011C4,15.906 4.895,15.011 6,15.011H11.799C11.799,15.011 17,6 24,6Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"/>
<path
android:pathData="M32,24H44"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<vector
android:height="108dp"
android:width="108dp"
android:viewportHeight="108"
android:viewportWidth="108"
xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z"/>
<path android:fillColor="#00000000" android:pathData="M9,0L9,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,0L19,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M29,0L29,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M39,0L39,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M49,0L49,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M59,0L59,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M69,0L69,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M79,0L79,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M89,0L89,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M99,0L99,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,9L108,9"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,19L108,19"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,29L108,29"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,39L108,39"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,49L108,49"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,59L108,59"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,69L108,69"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,79L108,79"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,89L108,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,99L108,99"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,29L89,29"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,39L89,39"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,49L89,49"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,59L89,59"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,69L89,69"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,79L89,79"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M29,19L29,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M39,19L39,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M49,19L49,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M59,19L59,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M69,19L69,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M79,19L79,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
</vector>

View File

@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M15,8C8.925,8 4,12.925 4,19C4,30 17,40 24,42.326C31,40 44,30 44,19C44,12.925 39.075,8 33,8C29.28,8 25.991,9.847 24,12.674C22.009,9.847 18.72,8 15,8Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#FF0000"
android:strokeColor="#FF0000"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,34 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M4,25C4,18.35 9.396,13 16,13H44"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#1976D2"
android:strokeLineCap="round"/>
<path
android:pathData="M38,7L44,13L38,19"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#1976D2"
android:strokeLineCap="round"/>
<path
android:pathData="M44,23C44,29.65 38.604,35 32,35H4"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#1976D2"
android:strokeLineCap="round"/>
<path
android:pathData="M10,41L4,35L10,29"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#1976D2"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,26 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M24,44C35.046,44 44,35.046 44,24C44,12.954 35.046,4 24,4C12.954,4 4,12.954 4,24C4,35.046 12.954,44 24,44Z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#333"/>
<path
android:pathData="M19,18V30"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M29,18V30"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,18 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M24,44C35.046,44 44,35.046 44,24C44,12.954 35.046,4 24,4C12.954,4 4,12.954 4,24C4,35.046 12.954,44 24,44Z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#333"/>
<path
android:pathData="M20,24V17.072L26,20.536L32,24L26,27.464L20,30.928V24Z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#333"/>
</vector>

View File

@ -0,0 +1,20 @@
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape>
<corners android:radius="5dp" />
<solid android:color="#D3D3D3" />
</shape>
</item>
<item android:id="@android:id/progress">
<clip>
<shape>
<corners android:radius="5dp" />
<gradient
android:startColor="#4891FF"
android:endColor="#6CE89E"
android:angle="0" />
</shape>
</clip>
</item>
</layer-list>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#4C9AF7" />
<stroke android:color="@color/white" android:width="4dp"/>
<size
android:width="16dp"
android:height="16dp" />
</shape>

View File

@ -0,0 +1,10 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:angle="45"
android:startColor="#4CAF50"
android:endColor="#03A9F4"
android:type="linear"
android:useLevel="false" />
<corners android:radius="16sp" />
</shape>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="32"
android:viewportHeight="32">
<path
android:pathData="M14.771,3C13.548,3 12.505,3.884 12.304,5.089L12.067,6.519C12.04,6.679 11.913,6.865 11.671,6.983C11.214,7.202 10.774,7.456 10.356,7.743C10.135,7.896 9.911,7.911 9.756,7.853L8.4,7.344C7.846,7.136 7.236,7.132 6.678,7.332C6.121,7.532 5.653,7.923 5.357,8.436L4.128,10.565C3.832,11.078 3.728,11.679 3.833,12.261C3.939,12.843 4.247,13.369 4.704,13.745L5.824,14.668C5.951,14.772 6.051,14.973 6.029,15.241C5.991,15.747 5.991,16.254 6.029,16.76C6.049,17.027 5.951,17.229 5.825,17.333L4.704,18.256C4.247,18.632 3.939,19.158 3.833,19.74C3.728,20.323 3.832,20.924 4.128,21.436L5.357,23.565C5.653,24.078 6.122,24.469 6.679,24.669C7.236,24.868 7.846,24.864 8.4,24.656L9.759,24.147C9.912,24.089 10.136,24.105 10.359,24.256C10.775,24.541 11.213,24.796 11.672,25.016C11.915,25.133 12.041,25.32 12.068,25.483L12.305,26.911C12.403,27.494 12.704,28.025 13.156,28.407C13.608,28.79 14.18,29 14.772,29H17.231C18.452,29 19.496,28.116 19.697,26.911L19.935,25.481C19.961,25.321 20.087,25.135 20.331,25.016C20.789,24.796 21.228,24.541 21.644,24.256C21.867,24.104 22.091,24.089 22.244,24.147L23.604,24.656C24.158,24.863 24.767,24.867 25.324,24.667C25.881,24.467 26.348,24.076 26.644,23.564L27.875,21.435C28.17,20.922 28.275,20.321 28.17,19.739C28.064,19.157 27.756,18.631 27.299,18.255L26.179,17.332C26.052,17.228 25.952,17.027 25.973,16.759C26.011,16.253 26.011,15.745 25.973,15.24C25.952,14.973 26.052,14.771 26.177,14.667L27.297,13.744C28.241,12.968 28.485,11.624 27.875,10.564L26.645,8.435C26.349,7.922 25.881,7.531 25.324,7.331C24.767,7.132 24.157,7.136 23.603,7.344L22.243,7.853C22.091,7.911 21.867,7.895 21.644,7.743C21.226,7.456 20.787,7.202 20.331,6.983C20.087,6.867 19.961,6.68 19.935,6.519L19.696,5.089C19.599,4.505 19.298,3.975 18.846,3.592C18.394,3.21 17.821,3 17.229,3H14.772H14.771ZM16,21C17.326,21 18.598,20.473 19.535,19.535C20.473,18.598 21,17.326 21,16C21,14.674 20.473,13.402 19.535,12.465C18.598,11.527 17.326,11 16,11C14.674,11 13.402,11.527 12.465,12.465C11.527,13.402 11,14.674 11,16C11,17.326 11.527,18.598 12.465,19.535C13.402,20.473 14.674,21 16,21Z"
android:fillColor="#181B3A"
android:fillType="evenOdd"/>
</vector>

View File

@ -0,0 +1,27 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M10.365,41.632C6.449,37.981 4,32.777 4,27C4,15.954 12.954,7 24,7C35.046,7 44,15.954 44,27C44,32.777 41.551,37.981 37.635,41.632"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M15.137,36.511C12.592,34.138 11,30.755 11,27C11,19.82 16.82,14 24,14C31.18,14 37,19.82 37,27C37,30.755 35.408,34.138 32.862,36.511"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M19.91,31.39C18.735,30.294 18,28.733 18,27C18,23.686 20.686,21 24,21C27.314,21 30,23.686 30,27C30,28.733 29.265,30.294 28.09,31.39"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,38 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M35,16C37.761,16 40,13.761 40,11C40,8.239 37.761,6 35,6C32.239,6 30,8.239 30,11C30,13.761 32.239,16 35,16Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"/>
<path
android:pathData="M13,29C15.761,29 18,26.761 18,24C18,21.239 15.761,19 13,19C10.239,19 8,21.239 8,24C8,26.761 10.239,29 13,29Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"/>
<path
android:pathData="M30,13.575L17.339,21.245"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M17.338,26.564L30.679,34.447"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M35,32C37.761,32 40,34.239 40,37C40,39.761 37.761,42 35,42C32.239,42 30,39.761 30,37C30,34.239 32.239,32 35,32Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"/>
</vector>

View File

@ -0,0 +1,27 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M8,44V4H31L40,14.5V44H8Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M32,14L26,16.969V31.5"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M20.5,31.5m-5.5,0a5.5,5.5 0,1 1,11 0a5.5,5.5 0,1 1,-11 0"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
</selector>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
</selector>

View File

@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M15,8C8.925,8 4,12.925 4,19C4,30 17,40 24,42.326C31,40 44,30 44,19C44,12.925 39.075,8 33,8C29.28,8 25.991,9.847 24,12.674C22.009,9.847 18.72,8 15,8Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,34 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M4,25C4,18.35 9.396,13 16,13H44"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M38,7L44,13L38,19"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M44,23C44,29.65 38.604,35 32,35H4"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M10,41L4,35L10,29"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,26 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M24,6V42C17,42 11.799,32.839 11.799,32.839H6C4.895,32.839 4,31.944 4,30.839V17.011C4,15.906 4.895,15.011 6,15.011H11.799C11.799,15.011 17,6 24,6Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"/>
<path
android:pathData="M32,24H44"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M38,18V30"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,23 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M24,44C29.523,44 34.523,41.761 38.142,38.142C41.761,34.523 44,29.523 44,24C44,18.477 41.761,13.477 38.142,9.858C34.523,6.239 29.523,4 24,4C18.477,4 13.477,6.239 9.858,9.858C6.239,13.477 4,18.477 4,24C4,29.523 6.239,34.523 9.858,38.142C13.477,41.761 18.477,44 24,44Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"/>
<path
android:pathData="M24,28.625V24.625C27.314,24.625 30,21.938 30,18.625C30,15.311 27.314,12.625 24,12.625C20.686,12.625 18,15.311 18,18.625"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M24,37.625C25.381,37.625 26.5,36.506 26.5,35.125C26.5,33.744 25.381,32.625 24,32.625C22.619,32.625 21.5,33.744 21.5,35.125C21.5,36.506 22.619,37.625 24,37.625Z"
android:fillColor="#333"
android:fillType="evenOdd"/>
</vector>

View File

@ -0,0 +1,133 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.activity.AudioPlayerActivity">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/line"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.80" />
<View
android:id="@+id/view"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="50dp"
android:layout_marginTop="75dp"
android:layout_marginEnd="50dp"
android:layout_marginBottom="75dp"
android:background="@drawable/rounded_rectangle_gradient"
app:layout_constraintBottom_toTopOf="@id/seek_bar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/back" />
<ImageView
android:id="@+id/back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:src="@drawable/back"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/favorite"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/un_like"
app:layout_constraintBottom_toTopOf="@+id/image"
app:layout_constraintStart_toEndOf="@+id/image" />
<ImageView
android:id="@+id/image"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="50dp"
android:scaleType="centerInside"
android:src="@mipmap/placeholder"
app:layout_constraintBottom_toBottomOf="@id/view"
app:layout_constraintEnd_toEndOf="@id/view"
app:layout_constraintStart_toStartOf="@id/view"
app:layout_constraintTop_toTopOf="@id/view" />
<ImageView
android:id="@+id/loop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/un_loop"
app:layout_constraintBottom_toBottomOf="@+id/view"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/image" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:textColor="@color/black"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/back"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/back" />
<SeekBar
android:id="@+id/seek_bar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="50dp"
android:layout_marginEnd="50dp"
android:layout_marginBottom="50dp"
android:maxHeight="5dp"
android:progress="50"
android:progressDrawable="@drawable/progress_gradient"
android:thumb="@drawable/progress_thumb"
app:layout_constraintBottom_toTopOf="@+id/line"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<ImageView
android:id="@+id/min"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:src="@drawable/down"
app:layout_constraintBottom_toBottomOf="@id/seek_bar"
app:layout_constraintEnd_toStartOf="@+id/seek_bar"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/seek_bar" />
<ImageView
android:id="@+id/max"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
android:src="@drawable/up"
app:layout_constraintBottom_toBottomOf="@id/seek_bar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/seek_bar"
app:layout_constraintTop_toTopOf="@+id/seek_bar" />
<ImageView
android:id="@+id/play"
android:layout_width="80dp"
android:layout_height="80dp"
android:background="@drawable/rounded_rectangle_gradient"
android:padding="10dp"
android:src="@drawable/play"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/seek_bar" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.activity.CategoryActivity">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:src="@drawable/back"
app:layout_constraintBottom_toBottomOf="@+id/title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/title" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/title" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".ui.activity.MainActivity">
<ImageView
android:id="@+id/setting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:src="@drawable/setting"
app:layout_constraintBottom_toBottomOf="@+id/title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/title" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:gravity="center_vertical"
android:text="@string/app_name"
android:textColor="@color/black"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
app:layout_constraintBottom_toTopOf="@+id/tab_layout"
app:layout_constraintTop_toBottomOf="@+id/title" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
android:background="@android:color/transparent"
app:layout_constraintBottom_toBottomOf="parent"
app:tabIndicatorHeight="0dp"
app:tabRippleColor="@android:color/transparent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,101 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp"
tools:context=".ui.activity.SettingActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:id="@+id/back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="9dp"
android:src="@drawable/back" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="@string/setting"
android:textSize="24sp"
android:textStyle="bold" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:orientation="horizontal"
android:padding="16dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/version" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:layout_weight="1"
android:text="@string/version"
android:textSize="16sp" />
<TextView
android:id="@+id/version"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:clickable="true"
android:focusable="true"
android:orientation="horizontal"
android:padding="16dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/share" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:layout_weight="1"
android:text="@string/share"
android:textSize="16sp" />
<ImageView
android:id="@+id/share"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/share_to" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:activity=".activity.SplashActivity">
<ImageView
android:id="@+id/image"
android:layout_width="150dp"
android:layout_height="150dp"
android:src="@mipmap/ic_launcher"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.388" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:text="@string/app_name"
android:textSize="25sp"
android:textStyle="bold"
android:gravity="center"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/image" />
<ProgressBar
android:id="@+id/progress"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="0dp"
android:layout_height="5dp"
android:layout_marginStart="53dp"
android:layout_marginEnd="53dp"
android:layout_marginBottom="80dp"
android:max="100"
android:progress="0"
android:progressDrawable="@drawable/progress_gradient"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.fragment.AudioFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
</FrameLayout>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.fragment.CategoryFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.fragment.FavoriteFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="150dp"
android:background="@drawable/rounded_rectangle_gradient"
android:backgroundTint="@color/white">
<ImageView
android:id="@+id/imageView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="16dp"
android:scaleType="centerInside"
app:layout_constraintBottom_toTopOf="@id/textView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/like"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:src="@drawable/un_like"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginBottom="16dp"
android:background="@drawable/rounded_rectangle_gradient"
android:ellipsize="end"
android:maxLines="1"
android:paddingStart="10dp"
android:paddingTop="5dp"
android:paddingEnd="10dp"
android:paddingBottom="5dp"
android:text="@string/app_name"
android:textColor="@color/black"
android:textSize="18sp"
android:textStyle="bold"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="15dp"
android:background="@drawable/rounded_rectangle_gradient">
<ImageView
android:id="@+id/image_view"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginTop="20dp"
android:layout_marginBottom="12dp"
app:layout_constraintBottom_toTopOf="@+id/text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:textStyle="bold"
android:gravity="center"
android:text="@string/app_name"
android:textSize="14sp"
app:layout_constraintTop_toBottomOf="@+id/image_view" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 598 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View File

@ -0,0 +1,7 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Base.Theme.FunnyPrankSounds" parent="Theme.Material3.DayNight.NoActionBar">
<!-- Customize your dark theme here. -->
<!-- <item name="colorPrimary">@color/my_dark_primary</item> -->
</style>
</resources>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="gray">#757575</color>
</resources>

View File

@ -0,0 +1,8 @@
<resources>
<string name="app_name">Funny Prank Sounds</string>
<!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string>
<string name="setting">Setting</string>
<string name="version">Version</string>
<string name="share">Share</string>
</resources>

View File

@ -0,0 +1,9 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Base.Theme.FunnyPrankSounds" parent="Theme.Material3.DayNight.NoActionBar">
<!-- Customize your light theme here. -->
<!-- <item name="colorPrimary">@color/my_light_primary</item> -->
</style>
<style name="Theme.FunnyPrankSounds" parent="Base.Theme.FunnyPrankSounds" />
</resources>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?><!--
Sample backup rules file; uncomment and customize as necessary.
See https://developer.android.com/guide/topics/data/autobackup
for details.
Note: This file is ignored for devices older that API 31
See https://developer.android.com/about/versions/12/backup-restore
-->
<full-backup-content>
<!--
<include domain="sharedpref" path="."/>
<exclude domain="sharedpref" path="device.xml"/>
-->
</full-backup-content>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?><!--
Sample data extraction rules file; uncomment and customize as necessary.
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
for details.
-->
<data-extraction-rules>
<cloud-backup>
<!-- TODO: Use <include> and <exclude> to control what is backed up.
<include .../>
<exclude .../>
-->
</cloud-backup>
<!--
<device-transfer>
<include .../>
<exclude .../>
</device-transfer>
-->
</data-extraction-rules>

View File

@ -0,0 +1,17 @@
package com.prank.funnypranksounds;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}

4
build.gradle.kts Normal file
View File

@ -0,0 +1,4 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
alias(libs.plugins.android.application) apply false
}

21
gradle.properties Normal file
View File

@ -0,0 +1,21 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. For more details, visit
# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true

22
gradle/libs.versions.toml Normal file
View File

@ -0,0 +1,22 @@
[versions]
agp = "8.5.1"
junit = "4.13.2"
junitVersion = "1.2.1"
espressoCore = "3.6.1"
appcompat = "1.7.0"
material = "1.12.0"
activity = "1.9.3"
constraintlayout = "2.2.0"
[libraries]
junit = { group = "junit", name = "junit", version.ref = "junit" }
ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }

BIN
gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,6 @@
#Thu Dec 19 15:06:18 CST 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https://mirrors.huaweicloud.com/repository/toolkit/gradle/gradle-8.7-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

185
gradlew vendored Normal file
View File

@ -0,0 +1,185 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"

89
gradlew.bat vendored Normal file
View File

@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

24
settings.gradle.kts Normal file
View File

@ -0,0 +1,24 @@
pluginManagement {
repositories {
google {
content {
includeGroupByRegex("com\\.android.*")
includeGroupByRegex("com\\.google.*")
includeGroupByRegex("androidx.*")
}
}
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
rootProject.name = "Funny Prank Sounds"
include(":app")