Skip to content

Commit 934d319

Browse files
authored
initial commit
1 parent 0406f7a commit 934d319

52 files changed

Lines changed: 1614 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

app/build.gradle

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
plugins {
2+
id 'com.android.application'
3+
}
4+
5+
android {
6+
compileSdk 34
7+
8+
defaultConfig {
9+
applicationId "project.first.audiometrysimulator"
10+
minSdkVersion 27
11+
targetSdkVersion 34
12+
versionCode 20
13+
versionName "2.0"
14+
}
15+
16+
17+
compileOptions {
18+
sourceCompatibility JavaVersion.VERSION_17
19+
targetCompatibility JavaVersion.VERSION_17
20+
}
21+
namespace 'project.first.audiometrysimulator'
22+
}
23+
24+
dependencies {
25+
implementation 'androidx.appcompat:appcompat:1.6.1'
26+
implementation 'com.google.android.material:material:1.11.0'
27+
implementation 'com.github.onlynight:WaveView:1.0.0'
28+
implementation 'com.github.abdularis:TapHoldUpButton:0.1.2'
29+
implementation 'com.github.husaynhakeem:about-page:0.1.1'
30+
implementation 'com.github.antonKozyriatskyi:CircularProgressIndicator:1.3.0'
31+
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
32+
}

app/proguard-rules.pro

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Add project specific ProGuard rules here.
2+
# You can control the set of applied configuration files using the
3+
# proguardFiles setting in build.gradle.
4+
#
5+
# For more details, see
6+
# http://developer.android.com/guide/developing/tools/proguard.html
7+
8+
# If your project uses WebView with JS, uncomment the following
9+
# and specify the fully qualified class name to the JavaScript interface
10+
# class:
11+
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12+
# public *;
13+
#}
14+
15+
# Uncomment this to preserve the line number information for
16+
# debugging stack traces.
17+
#-keepattributes SourceFile,LineNumberTable
18+
19+
# If you keep the line number information, uncomment this to
20+
# hide the original source file name.
21+
#-renamesourcefileattribute SourceFile

app/src/main/AndroidManifest.xml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
3+
4+
5+
6+
<application
7+
android:allowBackup="true"
8+
android:icon="@drawable/icon"
9+
android:label="@string/app_name"
10+
android:roundIcon="@drawable/icon"
11+
android:supportsRtl="true"
12+
android:theme="@style/Theme.AudiometrySimulator">
13+
<activity
14+
android:name=".TestResultActivity"
15+
android:label="Your test resul"
16+
android:exported="false" />
17+
<activity
18+
android:name=".AboutActivity"
19+
android:exported="false" />
20+
<activity
21+
android:name=".CheckUpActivity"
22+
android:label="Test your ears"
23+
android:noHistory="true"
24+
android:parentActivityName=".MainActivity" />
25+
<activity
26+
android:name=".ExploreActivity"
27+
android:parentActivityName=".MainActivity" />
28+
<activity
29+
android:name=".MainActivity"
30+
android:exported="true">
31+
<intent-filter>
32+
<action android:name="android.intent.action.MAIN" />
33+
34+
<category android:name="android.intent.category.LAUNCHER" />
35+
</intent-filter>
36+
</activity>
37+
38+
<meta-data
39+
android:name="preloaded_fonts"
40+
android:resource="@array/preloaded_fonts" />
41+
</application>
42+
43+
</manifest>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package project.first.audiometrysimulator;
2+
3+
import android.os.Bundle;
4+
import android.widget.Toast;
5+
6+
import androidx.appcompat.app.AppCompatActivity;
7+
8+
import husaynhakeem.com.aboutpage.AboutPage;
9+
import husaynhakeem.com.aboutpage.Item;
10+
11+
public class AboutActivity extends AppCompatActivity {
12+
13+
@Override
14+
protected void onCreate(Bundle savedInstanceState) {
15+
super.onCreate(savedInstanceState);
16+
17+
var page = new AboutPage(this)
18+
.setDescription(R.string.description)
19+
.setImage(R.drawable.icon)
20+
.addEmail("23BCS10607@cuchd.in")
21+
.addGithub("ErrorxCode/EarAcuity")
22+
.addItem(new Item("Version : 2.0",R.drawable.ic_verified,null))
23+
.create();
24+
25+
setContentView(page);
26+
27+
28+
}
29+
}
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
package project.first.audiometrysimulator;
2+
3+
import android.annotation.SuppressLint;
4+
import android.app.Activity;
5+
import android.content.ContentResolver;
6+
import android.content.ContentValues;
7+
import android.content.Context;
8+
import android.content.Intent;
9+
import android.content.res.AssetFileDescriptor;
10+
import android.media.MediaPlayer;
11+
import android.media.RingtoneManager;
12+
import android.net.Uri;
13+
import android.os.Environment;
14+
import android.provider.BaseColumns;
15+
import android.provider.ContactsContract;
16+
import android.provider.MediaStore;
17+
import android.util.AttributeSet;
18+
import android.view.MenuItem;
19+
import android.view.View;
20+
import android.widget.FrameLayout;
21+
import android.widget.ImageView;
22+
import android.widget.MediaController;
23+
import android.widget.PopupMenu;
24+
import android.widget.TextView;
25+
import android.widget.Toast;
26+
import android.widget.VideoView;
27+
28+
import androidx.activity.result.ActivityResultLauncher;
29+
import androidx.activity.result.contract.ActivityResultContracts;
30+
import androidx.annotation.NonNull;
31+
import androidx.annotation.Nullable;
32+
import androidx.appcompat.app.AppCompatActivity;
33+
import androidx.core.content.res.ResourcesCompat;
34+
35+
import java.io.File;
36+
import java.io.FileDescriptor;
37+
import java.io.FileOutputStream;
38+
import java.io.IOException;
39+
import java.io.InputStream;
40+
import java.io.OutputStream;
41+
42+
public class AudioSection extends FrameLayout {
43+
private AssetFileDescriptor audio;
44+
public RingtoneSetter ringtoneSetter;
45+
public ImageView play,menu;
46+
public VideoView wave;
47+
public boolean isPlaying = false;
48+
49+
public AudioSection(@NonNull Context context) {
50+
super(context);
51+
}
52+
53+
public AudioSection(@NonNull Context context, @Nullable AttributeSet attrs) {
54+
super(context, attrs);
55+
init(context,attrs);
56+
}
57+
58+
public AudioSection(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
59+
super(context, attrs, defStyleAttr);
60+
init(context,attrs);
61+
}
62+
63+
public AudioSection(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
64+
super(context, attrs, defStyleAttr, defStyleRes);
65+
init(context,attrs);
66+
}
67+
68+
private void init(Context context,AttributeSet attrs){
69+
var view = inflate(context, R.layout.audio_section,this);
70+
TextView title = view.findViewById(R.id.title);
71+
wave = view.findViewById(R.id.wave);
72+
menu = view.findViewById(R.id.menu);
73+
play = view.findViewById(R.id.play);
74+
75+
wave.setVideoURI(Uri.parse("android.resource://" + context.getPackageName() + "/" + R.raw.waveform));
76+
wave.setOnPreparedListener(mp -> mp.setLooping(true));
77+
78+
var attributes = context.obtainStyledAttributes(attrs,R.styleable.AudioSection);
79+
var titleStr = attributes.getString(R.styleable.AudioSection_title);
80+
var rawId = attributes.getResourceId(R.styleable.AudioSection_audio,0);
81+
audio = context.getResources().openRawResourceFd(rawId);
82+
title.setText(titleStr);
83+
84+
menu.setOnClickListener(v -> {
85+
var pref = context.getSharedPreferences("ringtone",Context.MODE_PRIVATE);
86+
var menu = new PopupMenu(context,v);
87+
menu.getMenu().add(0,1,0,"Set as Ringtone");
88+
menu.getMenu().add(0,0,1,"Restore ringtone");
89+
menu.setOnMenuItemClickListener(item -> {
90+
if (item.getItemId() == 1){
91+
String ringtone;
92+
if (!pref.getBoolean(titleStr,false)){
93+
ringtone = copyRingtoneToSystem(rawId,titleStr,context).toString();
94+
var editor = pref.edit();
95+
editor.putString("ringtone", ringtone);
96+
editor.putBoolean(titleStr,true);
97+
editor.apply();
98+
} else
99+
ringtone = pref.getString("ringtone","");
100+
101+
ringtoneSetter.setRingtone(Uri.parse(ringtone));
102+
} else {
103+
var contact = pref.getString("lastContact_" + titleStr,null);
104+
var ringtone = RingtoneManager.getActualDefaultRingtoneUri(context,RingtoneManager.TYPE_RINGTONE);
105+
ringtoneSetter.restoreRingtone(Uri.parse(contact),ringtone);
106+
}
107+
return true;
108+
});
109+
menu.show();
110+
});
111+
112+
attributes.recycle();
113+
}
114+
115+
public void play(MediaPlayer player){
116+
isPlaying = true;
117+
wave.setVisibility(View.VISIBLE);
118+
wave.start();
119+
play.setImageDrawable(ResourcesCompat.getDrawable(getResources(),R.drawable.paue,null));
120+
try {
121+
player.setDataSource(audio);
122+
player.prepare();
123+
player.start();
124+
} catch (Exception e){
125+
e.printStackTrace();
126+
}
127+
}
128+
129+
public void stop(MediaPlayer player){
130+
isPlaying = false;
131+
player.stop();
132+
player.reset();
133+
wave.pause();
134+
wave.setVisibility(View.INVISIBLE);
135+
play.setImageDrawable(ResourcesCompat.getDrawable(getResources(),R.drawable.play,null));
136+
}
137+
138+
private Uri copyRingtoneToSystem(int rawFile,String title,Context context){
139+
ContentResolver resolver = context.getContentResolver();
140+
var values = new ContentValues();
141+
values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_RINGTONES);
142+
values.put(MediaStore.MediaColumns.DISPLAY_NAME,title + ".mp3");
143+
values.put(MediaStore.MediaColumns.TITLE,title);
144+
values.put(MediaStore.MediaColumns.MIME_TYPE,"audio/mp3");
145+
values.put(MediaStore.Audio.Media.IS_RINGTONE,true);
146+
var newUri = resolver.insert(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,values);
147+
148+
try {
149+
var inputStream = getResources().openRawResource(rawFile);
150+
OutputStream fileOutputStream = getContext().getContentResolver().openOutputStream(newUri);
151+
byte[] buffer = new byte[1024];
152+
int length;
153+
while ((length = inputStream.read(buffer)) > 0) {
154+
fileOutputStream.write(buffer, 0, length);
155+
}
156+
inputStream.close();
157+
fileOutputStream.close();
158+
return newUri;
159+
} catch (IOException e) {
160+
e.printStackTrace();
161+
Toast.makeText(context, "IOExcpetion : " + e.getMessage(), Toast.LENGTH_SHORT).show();
162+
return null;
163+
}
164+
}
165+
166+
public static void setRingtone(Context context,Uri contact,Uri ringtone){
167+
var values = new ContentValues();
168+
values.put(ContactsContract.Contacts.CUSTOM_RINGTONE,ringtone.toString());
169+
context.getContentResolver().update(contact,values,null,null);
170+
171+
context.getSharedPreferences("ringtone",Context.MODE_PRIVATE)
172+
.edit()
173+
.putString("lastContact_" + getFileName(ringtone,context),contact.toString())
174+
.apply();
175+
}
176+
177+
public static String getFileName(Uri uri,Context context){
178+
var cursor = context.getContentResolver().query(uri, new String[]{MediaStore.MediaColumns.DISPLAY_NAME},null,null,null);
179+
if (cursor != null && cursor.moveToFirst()){
180+
@SuppressLint("Range") var name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
181+
cursor.close();
182+
return name;
183+
}
184+
return "default";
185+
}
186+
187+
public interface RingtoneSetter {
188+
void setRingtone(Uri ringtone);
189+
void restoreRingtone(Uri contact,Uri ringtone);
190+
}
191+
}

0 commit comments

Comments
 (0)