├── .gitignore
├── .idea
├── .gitignore
├── codeStyles
│ ├── Project.xml
│ └── codeStyleConfig.xml
├── gradle.xml
├── misc.xml
└── runConfigurations.xml
├── README.md
├── app
├── .gitignore
├── ReadMe.txt
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── example
│ │ └── free
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── free
│ │ │ ├── Activity1.java
│ │ │ ├── ChoiceActivity.java
│ │ │ ├── Classes
│ │ │ ├── ActivityCollector.java
│ │ │ ├── BaseActivity.java
│ │ │ ├── EachButton.java
│ │ │ ├── FFT.java
│ │ │ ├── HandleData.java
│ │ │ ├── LandEachButton.java
│ │ │ ├── MP3ToWav.java
│ │ │ ├── MP3ToWav1.java
│ │ │ ├── Music.java
│ │ │ └── MusicAdapter.java
│ │ │ ├── FourGameActivity.java
│ │ │ ├── GameActivity.java
│ │ │ ├── MainActivity.java
│ │ │ ├── Mp3Handle
│ │ │ ├── FrameData.java
│ │ │ ├── Mp3FileReader.java
│ │ │ └── MyMp3FileReader.java
│ │ │ ├── MusicActivity.java
│ │ │ ├── MusicViewActivity.java
│ │ │ ├── OriginChoiceActivity.java
│ │ │ ├── ResultActivity.java
│ │ │ └── WavHandle
│ │ │ └── WaveFileReader.java
│ └── res
│ │ ├── anim
│ │ └── anim.xml
│ │ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable
│ │ ├── _b2.jpg
│ │ ├── _note.jpg
│ │ ├── _r3.jpg
│ │ ├── b1.jpg
│ │ ├── b_bottom.jpg
│ │ ├── background_auto.xml
│ │ ├── ic_launcher_background.xml
│ │ ├── r2.jpg
│ │ ├── r4.jpg
│ │ └── shape.xml
│ │ ├── layout-land
│ │ └── activity_four_game.xml
│ │ ├── layout
│ │ ├── activity_1.xml
│ │ ├── activity_choice.xml
│ │ ├── activity_game.xml
│ │ ├── activity_main.xml
│ │ ├── activity_music.xml
│ │ ├── activity_music_view.xml
│ │ ├── activity_origin_choice.xml
│ │ ├── activity_result.xml
│ │ ├── music_item.xml
│ │ ├── toast.xml
│ │ └── toast_land.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ └── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── example
│ └── free
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | /.idea/navEditor.xml
9 | /.idea/assetWizardSettings.xml
10 | .DS_Store
11 | /build
12 | /captures
13 | .externalNativeBuild
14 | .cxx
15 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
18 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Free
2 | 一个自动识别音乐节奏点的仿节奏大师音游
3 |
4 | 功能:Free App仿照节奏大师的音游模式,大致实现读取本地音乐,自动识别节奏点并进行游戏的功能。
5 |
6 | 代码注释链接:https://blog.csdn.net/qq_43533416/article/details/105631991
7 |
8 | 备注:此APP为Android开发课程的大作业,背景图片来自网图非原创,未曾商用。
9 | 因为本人不是信号通信专业方向,节奏点的识别不够特别精确,尤其是有压缩的mp3文件,且能执行的音乐文件可能受大小限制,如果以后有机会会进行改良。
10 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/ReadMe.txt:
--------------------------------------------------------------------------------
1 | 功能:Free App仿照节奏大师的音游模式,大致实现读取本地音乐,自动识别节奏点并进行游戏的功能。
2 |
3 | 代码注释链接:https://blog.csdn.net/qq_43533416/article/details/105631991
4 |
5 | 备注:此APP为Android开发课程的大作业,背景图片来自网图非原创,未曾商用。
6 | 因为本人不是信号通信专业方向,节奏点的识别不够特别精确,尤其是有压缩的mp3文件,且能执行的音乐文件可能受大小限制,如果以后有机会会进行改良。
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 29
5 | buildToolsVersion "29.0.2"
6 | defaultConfig {
7 | applicationId "com.example.free"
8 | minSdkVersion 24
9 | targetSdkVersion 29
10 | versionCode 1
11 | versionName "1.0"
12 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | implementation fileTree(dir: 'libs', include: ['*.jar'])
24 | implementation 'androidx.appcompat:appcompat:1.0.2'
25 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
26 | testImplementation 'junit:junit:4.12'
27 | androidTestImplementation 'androidx.test:runner:1.1.1'
28 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
29 |
30 | implementation 'com.android.support:recyclerview-v7:29.0.2'
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
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
22 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/example/free/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.example.free;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.test.platform.app.InstrumentationRegistry;
6 | import androidx.test.ext.junit.runners.AndroidJUnit4;
7 |
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 |
11 | import static org.junit.Assert.*;
12 |
13 | /**
14 | * Instrumented test, which will execute on an Android device.
15 | *
16 | * @see Testing documentation
17 | */
18 | @RunWith(AndroidJUnit4.class)
19 | public class ExampleInstrumentedTest {
20 | @Test
21 | public void useAppContext() {
22 | // Context of the app under test.
23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
24 |
25 | assertEquals("com.example.free", appContext.getPackageName());
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
14 |
18 |
19 |
20 |
23 |
26 |
27 |
28 |
29 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/free/Activity1.java:
--------------------------------------------------------------------------------
1 | package com.example.free;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.appcompat.app.AppCompatActivity;
5 | import androidx.constraintlayout.widget.ConstraintLayout;
6 |
7 | import android.animation.ObjectAnimator;
8 | import android.app.Activity;
9 | import android.content.Context;
10 | import android.graphics.Color;
11 | import android.os.Bundle;
12 | import android.os.Handler;
13 | import android.os.Message;
14 | import android.util.Log;
15 | import android.util.Property;
16 | import android.view.LayoutInflater;
17 | import android.view.View;
18 | import android.view.animation.AnimationUtils;
19 | import android.widget.Button;
20 | import android.widget.LinearLayout;
21 | import android.widget.TextView;
22 | import android.widget.Toast;
23 |
24 | import org.w3c.dom.Text;
25 |
26 | import java.util.ArrayList;
27 | import java.util.Queue;
28 |
29 | import javax.xml.datatype.Duration;
30 |
31 | public class Activity1 extends AppCompatActivity {
32 | //
33 | // //EachButton eachButton1=null;//每个轨道的按钮list都放在数据域里
34 | // Button button_bottom;
35 | // int height;
36 | // ConstraintLayout constraintLayout;
37 | // static Toast toast;
38 | //
39 | // static ArrayList buttons=new ArrayList();
40 | //
41 | // @Override
42 | // protected void onCreate(Bundle savedInstanceState) {
43 | // super.onCreate(savedInstanceState);
44 | // setContentView(R.layout.activity_1);
45 | //
46 | // int width=getWindowManager().getDefaultDisplay().getWidth();
47 | // int height=getWindowManager().getDefaultDisplay().getHeight();
48 | // Button test1=findViewById(R.id.test_bottom1);
49 | // Button test2=findViewById(R.id.test_bottom2);
50 | // test1.setText(width+"");
51 | // test2.setText(height+"");
52 | // }
53 | //
54 | // constraintLayout=findViewById(R.id.constraintLayout);
55 | // EachButton eachButton1=new EachButton(getApplicationContext(),200,0,200,1300,0,2000);
56 | // eachButton1.setText("here1");
57 | //
58 | // height=eachButton1.height;
59 | //
60 | // //Toast.makeText(Activity1.this,"button1",Toast.LENGTH_SHORT).show();
61 | // //linearLayout.addView(eachButton1);
62 | // eachButton1.start(constraintLayout);
63 | //
64 | //// eachButton1.setOnClickListener(new View.OnClickListener() {
65 | //// @Override
66 | //// public void onClick(View v) {
67 | //// Toast.makeText(Activity1.this,eachButton1.getY()+"",Toast.LENGTH_SHORT).show();
68 | //// }
69 | //// });//button实际的布局位置没变,只是显示变了,点击原位置仍可以有事件响应
70 | //
71 | // EachButton eachButton2=new EachButton(getApplicationContext(),400,0 ,400,1200,500,2000,0);
72 | // eachButton2.setText("here2");
73 | // //linearLayout.addView(eachButton2);
74 | // eachButton2.start(constraintLayout);
75 | //
76 | // EachButton eachButton3=new EachButton(getApplicationContext(),600,0,600,1200,700,2000);
77 | // eachButton3.setText("here3");
78 | // //linearLayout.addView(eachButton3);
79 | // eachButton3.start(constraintLayout);
80 | //
81 | // buttons.add(eachButton1);
82 | // buttons.add(eachButton2);
83 | // buttons.add(eachButton3);
84 | //
85 | // Toast.makeText(getApplicationContext(),buttons.size()+"",Toast.LENGTH_SHORT).show();
86 | //
87 | // toast=new Toast(getApplicationContext());
88 | // //toast.show();
89 | //
90 | //
91 | //
92 | // button_bottom=findViewById(R.id.button_bottom);
93 | // button_bottom.setOnClickListener(new View.OnClickListener() {
94 | // @Override
95 | // public void onClick(View v) {
96 | // EachButton button=null;
97 | // try {
98 | // Toast.makeText(Activity1.this,buttons.size()+"",Toast.LENGTH_SHORT).show();
99 | // if (buttons.size() > 0)
100 | // button = buttons.get(0);
101 | // }
102 | // catch(Exception e){
103 | // e.printStackTrace();
104 | // }
105 | //
106 | // //Toast.makeText(Activity1.this,"here click",Toast.LENGTH_SHORT).show();
107 | // Log.d("testToast","here");
108 | // Context context=getApplicationContext();
109 | // View view =LayoutInflater.from(context).inflate(R.layout.toast, null);
110 | // //不然如果后面用setView(findViewById()),AppCompatActivity.findViewById()是无法识别的,会出错
111 | // /*LayoutInflater这个类的作用类似于findViewById()。
112 | // 不同点是LayoutInflater是用来找res/layout/下的xml布局文件,并且实例化;
113 | // 而findViewById()是找xml布局文件下的具体widget控件(如Button、TextView等)。
114 | // */
115 | //
116 | // toast.cancel();//让上一个取消,不然新的toast放不上去
117 | //
118 | //
119 | //
120 | //
121 | // //float buttonY=getButtonY();
122 | // //int[] location=new int[2];
123 | // //eachButton1.getLocationOnScreen(location);
124 | // //eachButton1.getLocationOnScreen(location);
125 | // TextView textView=view.findViewById(R.id.textView);
126 | //
127 | // /*
128 | // ObjectAnimator textAnimator=ObjectAnimator
129 | // .ofFloat(textView,"translationY", textView.getY(), textView.getY()+300)
130 | // .setDuration(1000);*/
131 | //
132 | // int d=(int)(button_bottom.getY()-button.getY());
133 | // if((d>-height&&d<-height/2)||(dheight/2)) {
134 | // textView.setText("good");
135 | // //textView.setTextColor(getResources().getColor(R.color.colorLightGreen));
136 | // constraintLayout.removeView(button);
137 | // buttons.remove(0);
138 | // button.state=false;
139 | // button.animator.cancel();//这里要取消动画,不然虽然视图里的button消失了,但button对象还在,动画还会继续执行
140 | // //button.viewRemoveButton(constraintLayout);
141 | //
142 | // ObjectAnimator.ofArgb(textView, "textColor",
143 | // Color.parseColor("#ff1B8A22"),
144 | // Color.parseColor("#001B8A22"))
145 | // .setDuration(1000)
146 | // .start();
147 | // }
148 | // else {
149 | // if(d<=height/2&&d>=-height/2){
150 | // textView.setText("best");
151 | // //textView.setTextColor(getResources().getColor(R.color.colorLightBlue));
152 | // constraintLayout.removeView(button);
153 | // buttons.remove(0);
154 | // button.state=false;
155 | // button.animator.cancel();
156 | // //button.viewRemoveButton(constraintLayout);
157 | //
158 | // ObjectAnimator.ofArgb(textView, "textColor",
159 | // Color.parseColor("#ff00bfff"),
160 | // Color.parseColor("#0000bfff"))
161 | // .setDuration(1000)
162 | // .start();
163 | // }
164 | // else{
165 | // textView.setText("");
166 | // }
167 | // }
168 | //
169 | //
170 | // //textView.setText(location[1]+" "+eachButton1.getY()+" "+button_bottom.getY());//getTop()得到的是控件距离父级的top的距离
171 | // toast=new Toast(context);
172 | // //LinearLayout toastView=(LinearLayout)toast.getView();
173 | // toast.setView(view);
174 | // Log.d("testToast","here1");
175 | // toast.setDuration(Toast.LENGTH_SHORT);
176 | //
177 | // view.animate().translationY(50)
178 | // .setDuration(1000);
179 | //
180 | //
181 | // toast.show();
182 | //
183 | // }
184 | // });
185 | //
186 | // /*
187 | // EachButton eachButton4=new EachButton(getApplicationContext(),300,0,300,500,500,3000);
188 | // eachButton3.setText("here3");
189 | // //linearLayout.addView(eachButton3);
190 | // //eachButton3.start(linearLayout);
191 | //
192 | // new Handler(new Handler.Callback() {
193 | // //不能动态设置开始时间
194 | // @Override
195 | // public boolean handleMessage(@NonNull Message msg) {
196 | // findViewById(R.id.textView).startAnimation(AnimationUtils.loadAnimation(getApplicationContext(),+R.anim.anim));
197 | // return false;
198 | // }
199 | // }).sendEmptyMessageDelayed(0,2000);*/
200 | // }
201 | //
202 | //// public float getButtonY(){
203 | //// return eachButton1.getTranslationY();
204 | //// }
205 |
206 | }
207 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/free/ChoiceActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.free;
2 |
3 | import androidx.appcompat.app.AppCompatActivity;
4 |
5 | import android.content.Intent;
6 | import android.os.Bundle;
7 | import android.view.View;
8 | import android.widget.Button;
9 | import android.widget.EditText;
10 | import android.widget.ProgressBar;
11 | import android.widget.Toast;
12 |
13 | import com.example.free.Classes.BaseActivity;
14 |
15 | public class ChoiceActivity extends BaseActivity {
16 |
17 |
18 | String musicPath;
19 | long musicSize;
20 | long musicTime;
21 |
22 |
23 | EditText window;
24 | EditText window_size;
25 | EditText multiplier;
26 | EditText duration;
27 | EditText roads;
28 | @Override
29 | protected void onCreate(Bundle savedInstanceState) {
30 | super.onCreate(savedInstanceState);
31 | setContentView(R.layout.activity_choice);
32 |
33 | setTitle("高级设置");
34 |
35 | Intent intent=getIntent();
36 | musicPath=intent.getStringExtra("musicPath");
37 | musicSize=intent.getLongExtra("musicSize",0);
38 | musicTime=intent.getLongExtra("musicTime",0);
39 |
40 |
41 | window=findViewById(R.id.window);
42 | window_size=findViewById(R.id.window_size);
43 | multiplier=findViewById(R.id.multiplier);
44 | duration=findViewById(R.id.duration);
45 | roads=findViewById(R.id.roads);
46 |
47 | Button click=findViewById(R.id.click);
48 | click.setOnClickListener(new View.OnClickListener() {
49 | @Override
50 | public void onClick(View v) {
51 |
52 | // ProgressBar progressBar=findViewById(R.id.progressBar1);
53 | // progressBar.setVisibility(View.VISIBLE);
54 |
55 | int windowInt=1024;
56 | int windowSizeInt=20;
57 | double multiplierDouble=1.5;
58 | int blockDuration=1000;
59 | int roadsCount=2;
60 |
61 | String s1=(window.getText()+"").trim();
62 | if(!s1.equals(""))
63 | windowInt=Integer.parseInt(s1);
64 |
65 | String s2=(window_size.getText()+"").trim();
66 | if(!s2.equals(""))
67 | windowSizeInt=Integer.parseInt(s2);
68 |
69 | String s3=(multiplier.getText()+"").trim();
70 | if(!s3.equals(""))
71 | multiplierDouble=Double.parseDouble(s3);
72 |
73 | String s4=(duration.getText()+"").trim();
74 | if(!s4.equals(""))
75 | blockDuration=Integer.parseInt(s4);
76 |
77 | String s5=(roads.getText()+"").trim();
78 | if(!s5.equals(""))
79 | roadsCount=Integer.parseInt(s5);
80 |
81 | Intent intent1;
82 | if(roadsCount==4)
83 | intent1=new Intent(getApplicationContext(),FourGameActivity.class);
84 | else
85 | intent1=new Intent(getApplicationContext(),GameActivity.class);
86 |
87 | intent1.putExtra("className","ChoiceActivity");//getClass().getName()带有根底
88 | // Toast.makeText(getApplicationContext(),getClass().getName(),Toast.LENGTH_SHORT).show();
89 | intent1.putExtra("window",windowInt);
90 | intent1.putExtra("windowSize",windowSizeInt);
91 | intent1.putExtra("multiplier",multiplierDouble);
92 | intent1.putExtra("duration",blockDuration);
93 | intent1.putExtra("musicPath",musicPath);
94 | intent1.putExtra("musicSize", musicSize);
95 | intent1.putExtra("musicTime",musicTime);
96 | startActivity(intent1);
97 |
98 |
99 | }
100 | });
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/free/Classes/ActivityCollector.java:
--------------------------------------------------------------------------------
1 | package com.example.free.Classes;
2 |
3 | import android.app.Activity;
4 |
5 | import java.util.ArrayList;
6 | import java.util.List;
7 |
8 | public class ActivityCollector {
9 | public static List activities=new ArrayList<>();
10 |
11 | public static void addActivity(Activity activity){
12 | activities.add(activity);
13 | }
14 | public static void removeActivity(Activity activity){
15 | activities.remove(activity);
16 | }
17 | public static void finishAll(){
18 | for(Activity activity:activities){
19 | if(!activity.isFinishing())
20 | activity.finish();
21 | }
22 | activities.clear();
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/free/Classes/BaseActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.free.Classes;
2 |
3 | import android.content.BroadcastReceiver;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.content.IntentFilter;
7 | import android.os.Bundle;
8 |
9 | import androidx.annotation.Nullable;
10 | import androidx.appcompat.app.AppCompatActivity;
11 |
12 | import com.example.free.MainActivity;
13 |
14 | public class BaseActivity extends AppCompatActivity {
15 |
16 | @Override
17 | protected void onCreate(@Nullable Bundle savedInstanceState) {
18 | super.onCreate(savedInstanceState);
19 | ActivityCollector.addActivity(this);
20 | }
21 |
22 | @Override
23 | protected void onDestroy() {
24 | super.onDestroy();
25 | ActivityCollector.removeActivity(this);
26 | }
27 |
28 | @Override
29 | protected void onResume() {
30 | super.onResume();
31 | IntentFilter intentFilter=new IntentFilter();
32 | intentFilter.addAction("force_offline");
33 | ForceOffLineReceiver receiver=new ForceOffLineReceiver();
34 | registerReceiver(receiver,intentFilter);
35 | }
36 |
37 | class ForceOffLineReceiver extends BroadcastReceiver{
38 | @Override
39 | public void onReceive(Context context, Intent intent) {
40 | ActivityCollector.finishAll();//把所有活动finish后再打开主页面的活动
41 | // Intent intent1=new Intent(context, MainActivity.class);
42 | // context.startActivity(intent1);
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/free/Classes/EachButton.java:
--------------------------------------------------------------------------------
1 | package com.example.free.Classes;
2 |
3 |
4 | import android.animation.Animator;
5 | import android.animation.ObjectAnimator;
6 | import android.content.Context;
7 | import android.content.Intent;
8 | import android.graphics.Color;
9 | import android.graphics.Path;
10 | import android.util.Property;
11 | import android.view.LayoutInflater;
12 | import android.view.View;
13 | import android.view.animation.LinearInterpolator;
14 | import android.widget.TextView;
15 | import android.widget.Toast;
16 |
17 | import androidx.appcompat.widget.AppCompatButton;
18 | import androidx.constraintlayout.widget.ConstraintLayout;
19 |
20 | import com.example.free.GameActivity;
21 | import com.example.free.R;
22 | import com.example.free.ResultActivity;
23 |
24 | import java.util.Timer;
25 | import java.util.TimerTask;
26 |
27 |
28 | public class EachButton extends AppCompatButton {
29 | int fromX=0;
30 | int fromY=0;
31 | int toX=0;
32 | int toY=0;
33 | int startTime=0;
34 | int time=0;
35 |
36 | int width=240;//px
37 | int height=120;
38 | // int width=80;//dp
39 | // int height=40;//dp
40 |
41 | // final int endWidth=240;//px
42 | // final int endHeight=120;
43 |
44 | ConstraintLayout mlayout;
45 | Context mcontext;
46 |
47 | public ObjectAnimator animator;
48 |
49 | public boolean state=true;//按钮的状态,是否还存在于视图中
50 |
51 | int path=0;//轨道
52 |
53 |
54 |
55 |
56 | public EachButton(Context context,int _width,int _height,int fx,int fy,int tox,int toy,int st,int t,int p){
57 | super(context);
58 |
59 | this.fromX=fx;
60 | this.fromY=fy;
61 | this.toX=tox;
62 | this.toY=toy;
63 | this.startTime=st;
64 | this.time=t;
65 |
66 | this.path=p;
67 |
68 | width=_width;
69 | height=_height;
70 |
71 | mcontext=context;
72 |
73 | this.setBackgroundColor(0xaaF8E097);
74 | //this.layout(fx,fy,fx+width,fy+height);
75 |
76 | // this.setVisibility(INVISIBLE);
77 | this.setWidth(width);
78 | this.setHeight(height);
79 | this.layout(1000,0,1000+width,height);
80 |
81 | //this.setWidth(80*441/160);
82 | //this.setHeight(40*441/160);//40dp*441ppi/160 px //setWidth()和后面getX()得到的也都是像素pixels,所以这里也用像素
83 |
84 |
85 | //this.start();
86 |
87 |
88 | }
89 |
90 | //继承的已有setVisibility(0)方法,getTranslationX(),getX()方法,
91 |
92 | public void start(ConstraintLayout layout){
93 | //
94 | // TranslateAnimation ta=new TranslateAnimation(fromX,toX,fromY,toY);
95 | // ta.setDuration(time);//动画时长 ms
96 | // ta.setStartOffset(startTime);//延时
97 | // //ta.setFillBefore(false);//动画结束时停在第一帧
98 | // //ta.setFillAfter(false);
99 | // /* final LinearLayout mlayout=layout;
100 | // EachButton eachButton=this;*/
101 | // //setStateValue(this,layout);
102 | // //this.setVisibility(INVISIBLE);
103 | // LinearInterpolator lin = new LinearInterpolator();//匀速运动
104 | // ta.setInterpolator(lin);
105 | //
106 | // layout=mlayout;
107 | //
108 | //
109 | // //setState(this,ta);
110 | // setStateValue(this);
111 | // layout.addView(this);//把addView放到onAnimationStart里面加载不出来
112 | //
113 | //
114 | // this.startAnimation(ta);//自动启动动画
115 | // //layout.removeView(this);
116 |
117 | //translateAnimation是表面呈现的移动,但布局没变,animator会随着变,方便获得移动中的位置
118 | mlayout=layout;
119 | //layout.addView(this);
120 | //ObjectAnimator.ofFloat(this, "translationY", fromY, toY).setDuration(time).setStartDelay(startTime);
121 | Path path=new Path();
122 | path.moveTo(fromX,fromY);//开始
123 | path.lineTo(toX,toY);//结束
124 | animator=ObjectAnimator.ofFloat(this,
125 | Property.of(EachButton.class,Float.class,"translationX"),
126 | Property.of(EachButton.class,Float.class,"translationY"),
127 | path);
128 |
129 | animator.setDuration(time);
130 | animator.setStartDelay(startTime);
131 |
132 | //animator.pause();
133 |
134 | LinearInterpolator lin = new LinearInterpolator();//匀速运动
135 | animator.setInterpolator(lin);
136 |
137 | final EachButton eachButton=this;
138 | animator.addListener(new Animator.AnimatorListener() {
139 | @Override
140 | public void onAnimationStart(Animator animation) {
141 | mlayout.addView(eachButton);
142 | }
143 |
144 | @Override
145 | public void onAnimationEnd(Animator animation) {
146 | mlayout.removeView(eachButton);
147 |
148 | if(eachButton.state) {
149 | View view = LayoutInflater.from(mcontext).inflate(R.layout.toast, null);
150 | TextView textView = view.findViewById(R.id.textView);
151 | textView.setText("miss");
152 | //textView.setTextColor(Color.parseColor("#909090"));
153 | //textView.setTextColor(getResources().getColor(R.color.colorGray));
154 | //Toast toast=new Toast(mcontext);
155 | Toast toast = GameActivity.toast;//方便被activity1里面新的点击替代,如果是新的可能替代不了
156 | toast.setView(view);
157 | toast.setDuration(Toast.LENGTH_SHORT);
158 |
159 | /*
160 | ObjectAnimator textAnimator=ObjectAnimator
161 | .ofFloat(textView,"translationY", textView.getY(), textView.getY()+200)
162 | .setDuration(1000);*/
163 | ObjectAnimator.ofArgb(textView, "textColor",
164 | Color.parseColor("#ff333333"),
165 | Color.parseColor("#00333333"))
166 | .setDuration(1000)
167 | .start();
168 | toast.show();
169 |
170 | GameActivity.buttons.get(eachButton.path).remove(0);
171 | GameActivity.missTimes+=1;
172 |
173 | if((GameActivity.buttons.get(0).size()+GameActivity.buttons.get(1).size()==0)&&GameActivity.activityState) {
174 | final Intent iintent = new Intent(mcontext, ResultActivity.class);
175 | iintent.putExtra("wholeScore",GameActivity.wholeScore);
176 | iintent.putExtra("resultScore",GameActivity.resultScore);
177 | iintent.putExtra("bestTimes",GameActivity.bestTimes);
178 | iintent.putExtra("goodTimes",GameActivity.goodTimes);
179 | iintent.putExtra("missTimes",GameActivity.missTimes);
180 | TimerTask task = new TimerTask(){
181 | public void run(){
182 | mcontext.startActivity(iintent);
183 | }
184 | };
185 | Timer timer = new Timer();
186 | timer.schedule(task, 2000);
187 |
188 | }
189 |
190 | }
191 |
192 | }
193 |
194 | @Override
195 | public void onAnimationCancel(Animator animation) {
196 |
197 | }
198 |
199 | @Override
200 | public void onAnimationRepeat(Animator animation) {
201 |
202 | }
203 | });
204 | // animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
205 | // @Override
206 | // public void onAnimationUpdate(ValueAnimator animation) {
207 | // eachButton.setWidth(width+(int)animation.getCurrentPlayTime()/time*(endWidth-width));
208 | // eachButton.setWidth(height+(int)animation.getCurrentPlayTime()/time*(endHeight-height));
209 | // }
210 | // });
211 | animator.start();
212 | /*
213 | layout=mlayout;
214 | layout.addView(this);
215 | final EachButton eachButton=this;
216 | this.animate().translationY(toY)
217 | .setDuration(time).setStartDelay(startTime)
218 | .withEndAction(new Runnable() {
219 | @Override
220 | public void run() {
221 | layout.removeView(eachButton);
222 | }
223 | });
224 | */
225 | }
226 |
227 |
228 |
229 | /*
230 | public void viewRemoveButton(ConstraintLayout mlayout){
231 | mlayout.removeView(this);
232 | }
233 | */
234 |
235 | /*
236 | public void setState(final EachButton eachButton,TranslateAnimation ta){
237 |
238 | ta.setAnimationListener(new Animation.AnimationListener() {
239 |
240 | @Override
241 | public void onAnimationStart(Animation animation) {
242 | //layout.addView(eachButton);
243 | Log.d("state","here");
244 | //eachButton.setVisibility(VISIBLE);
245 |
246 | }
247 |
248 | @Override
249 | public void onAnimationEnd(Animation animation) {
250 | //Log.d("state","there");
251 | //eachButton.setVisibility(INVISIBLE);
252 | mlayout.removeView(eachButton);
253 | eachButton.state=false;
254 |
255 | View view =LayoutInflater.from(mcontext).inflate(R.layout.toast, null);
256 | TextView textView=view.findViewById(R.id.textView);
257 | textView.setText("miss");
258 | //textView.setTextColor(Color.parseColor("#909090"));
259 | textView.setTextColor(getResources().getColor(R.color.colorGray));
260 | Toast toast=new Toast(mcontext);
261 | toast.setView(view);
262 | toast.setDuration(Toast.LENGTH_SHORT);
263 | toast.show();
264 |
265 | Activity1.buttons.remove(0);
266 |
267 |
268 | }
269 |
270 | @Override
271 | public void onAnimationRepeat(Animation animation) {
272 |
273 | }
274 | });
275 |
276 | this.addOnLayoutChangeListener(new OnLayoutChangeListener() {
277 | @Override
278 | public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
279 | Toast.makeText(getContext(),top+"",Toast.LENGTH_SHORT).show();
280 | }
281 | });
282 |
283 |
284 | }
285 | */
286 |
287 | /*
288 | public void setStateValue(final EachButton eachButton){
289 |
290 |
291 | ValueAnimator valueAnimator= ValueAnimator.ofInt(eachButton.fromY,eachButton.toY);
292 | valueAnimator.setDuration(eachButton.time);
293 | valueAnimator.setStartDelay(eachButton.startTime);
294 |
295 | valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
296 | @Override
297 | public void onAnimationUpdate(ValueAnimator animation) {
298 | int curValue = (int)animation.getAnimatedValue();
299 | //layout(left,top,right,bottom)
300 | eachButton.layout(eachButton.fromX,curValue,eachButton.fromX+150,curValue+100);
301 | //if(curValue==1)
302 | //linearLayout.addView(eachButton);
303 | //eachButton.setVisibility(VISIBLE);
304 | if(curValue==eachButton.toY)
305 | //eachButton.setVisibility(INVISIBLE);
306 | mlayout.removeView(eachButton);
307 | }
308 | });
309 | valueAnimator.start();
310 |
311 | }
312 | */
313 |
314 |
315 |
316 |
317 | }
318 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/free/Classes/FFT.java:
--------------------------------------------------------------------------------
1 | package com.example.free.Classes;
2 |
3 | public class FFT {
4 |
5 | int n, m;
6 |
7 | // Lookup tables. Only need to recompute when size of FFT changes.
8 | double[] cos;
9 | double[] sin;
10 |
11 | public FFT(int n) {
12 | this.n = n;
13 | this.m = (int) (Math.log(n) / Math.log(2));//2的几次方
14 |
15 | // Make sure n is a power of 2
16 | if (n != (1 << m))
17 | throw new RuntimeException("FFT length must be power of 2");//2的幂次方
18 |
19 | // precompute tables
20 | cos = new double[n / 2];
21 | sin = new double[n / 2];
22 |
23 | for (int i = 0; i < n / 2; i++) {
24 | cos[i] = Math.cos(-2 * Math.PI * i / n);
25 | sin[i] = Math.sin(-2 * Math.PI * i / n);
26 | }
27 |
28 | }
29 |
30 |
31 | //x是实部,y是虚部
32 | public void fft(double[] x, double[] y) {
33 | int i, j, k, n1, n2, a;
34 | double c, s, t1, t2;
35 |
36 | //n=16;
37 | // Bit-reverse
38 | j = 0;
39 | n2 = n / 2;//8
40 | for (i = 1; i < n - 1; i++) {
41 | n1 = n2;//8
42 | while (j >= n1) {
43 | j = j - n1;//0 4 0 4 0
44 | n1 = n1 / 2;//4 4 4 4 4
45 | }
46 | j = j + n1;//8 4 12 8 4 12 8 4 12
47 |
48 | if (i < j) {// i j,1 8,2 4,3 12, 4 8,5 4,6 12, 7 8,8 4,9 12 ,,10 8,11 4,12 12, 13 8,14 4,
49 | // i j交换,1 8,2 4,3 12, 4 8, ,6 12, 7 8, ,9 12 ,, , , , , , ; 8, 4, 12, 1, 5, 3, 2, 7, 6, 10, 11, 9, 13, 14, 15, 16,
50 | t1 = x[i];
51 | x[i] = x[j];
52 | x[j] = t1;
53 | t1 = y[i];
54 | y[i] = y[j];
55 | y[j] = t1;
56 | }
57 | }
58 |
59 | // FFT
60 | n1 = 0;
61 | n2 = 1;
62 | //m=4
63 | for (i = 0; i < m; i++) {
64 | n1 = n2;//1
65 | n2 = n2 + n2;//2
66 | a = 0;
67 |
68 | for (j = 0; j < n1; j++) {
69 | c = cos[a];
70 | s = sin[a];
71 | a += 1 << (m - i - 1);
72 |
73 | for (k = j; k < n; k = k + n2) {
74 | t1 = c * x[k + n1] - s * y[k + n1];
75 | t2 = s * x[k + n1] + c * y[k + n1];
76 | x[k + n1] = x[k] - t1;
77 | y[k + n1] = y[k] - t2;
78 | x[k] = x[k] + t1;
79 | y[k] = y[k] + t2;
80 | }
81 | }
82 | }
83 | }
84 |
85 | //采集的信号虚部为0即可
86 | public static void main(String[] args){
87 | int N=16;
88 | FFT fft=new FFT(N);
89 |
90 | double[] re=new double[N];
91 | double[] im=new double[N];
92 |
93 | // Impulse
94 | re[0] = 1; im[0] = 0;
95 | for(int i=1; i allTime,int sampling,long musicTime,int _window,int window_size,double multiplier){
23 |
24 | final int window=_window;//样本窗口越大,,可能超过阈值的越多
25 | final int THRESHOLD_WINDOW_SIZE=window_size;//阈值左右各取多少个样本窗口的光谱通量!!!!越慢的歌要的越少,size越大,块数越多
26 | final double MULTIPLIER=multiplier;//阈值的加权值!!!!越慢的歌要的越高(快的歌太高,短时间变得快,块数越少)
27 | // final double lean=0.95;
28 |
29 |
30 |
31 | double[] dataFFT;//频谱
32 | List spectralFlux = new ArrayList<>();//每个样本窗口的光谱通量
33 | List leanRate = new ArrayList<>();//每个样本窗口的光谱通量
34 |
35 | List threshold = new ArrayList<>( );//每个样本窗口的阈值
36 | List leanRateAverage=new ArrayList<>();//附近几个的平均斜率,如果它的斜率大于平均值,则为突然变化值
37 |
38 |
39 | int len = data.length;
40 |
41 | int m=len/window;//样本窗口数 //近似。。待定加一
42 |
43 | dataFFT=new double[len];
44 | double[] dataFFTVariation=new double[len-m];
45 |
46 |
47 | FFT fft=new FFT(window);//本地类
48 |
49 | double[] re=new double[window];//实部
50 | double[] im=new double[window];//虚部,为0
51 |
52 | double max=re[0];
53 | double min=re[0];
54 |
55 | for(int k=0;k0){
68 | dataFFTVariation[k*window+i-1-k]=dataFFT[k*window+i]-dataFFT[k*window+i-1];
69 | double value=dataFFTVariation[k*window+i-1-k];
70 | flux+=value<0?0:value;
71 | //flux+=value;
72 | }
73 | }
74 | // if(flux>max)max=flux;
75 | // if(flux0.01)
87 | //// allTime.add(i*window/sampling*1000);
88 | // }
89 | // System.out.println();
90 |
91 |
92 | //阈值
93 | int delete=10;
94 | for(int i=0;i0&&(time-allTime.get(allTime.size()-1))>100)||allTime.size()<1)
112 | allTime.add(time);//不知道为什么只有16的时候效果比较好..平均采样率16000
113 | }
114 | }
115 | for(int i=0;i<5;i++)
116 | allTime.remove(0);
117 | //System.out.println();
118 |
119 | // for(int i=1;ileanRate.get(i-1)*0.05)
121 | // allTime.add(i*window/sampling*1000);
122 | // }
123 | //
124 | // for(int i=1;iMath.abs(spectralFlux.get(i-1))*0.1)
126 | // allTime.add(i*window/sampling*1000);
127 | // }
128 | //System.out.println("here is allTime length:"+allTime.size());
129 |
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/free/Classes/LandEachButton.java:
--------------------------------------------------------------------------------
1 | package com.example.free.Classes;
2 |
3 |
4 | import android.animation.Animator;
5 | import android.animation.ObjectAnimator;
6 | import android.content.Context;
7 | import android.content.Intent;
8 | import android.graphics.Color;
9 | import android.graphics.Path;
10 | import android.util.Property;
11 | import android.view.LayoutInflater;
12 | import android.view.View;
13 | import android.view.animation.LinearInterpolator;
14 | import android.widget.TextView;
15 | import android.widget.Toast;
16 |
17 | import androidx.appcompat.widget.AppCompatButton;
18 | import androidx.constraintlayout.widget.ConstraintLayout;
19 |
20 | import com.example.free.FourGameActivity;
21 | import com.example.free.R;
22 | import com.example.free.ResultActivity;
23 |
24 | import java.util.Timer;
25 | import java.util.TimerTask;
26 |
27 |
28 | public class LandEachButton extends AppCompatButton {
29 | int fromX=0;
30 | int fromY=0;
31 | int toX=0;
32 | int toY=0;
33 | int startTime=0;
34 | int time=0;
35 |
36 | int width=240;//px
37 | int height=120;
38 |
39 | // final int endWidth=240;//px
40 | // final int endHeight=120;
41 |
42 | ConstraintLayout mlayout;
43 | Context mcontext;
44 |
45 | public ObjectAnimator animator;
46 |
47 | public boolean state=true;//按钮的状态,是否还存在于视图中
48 |
49 | int path=0;//轨道
50 |
51 |
52 |
53 |
54 | public LandEachButton(Context context,int _width,int _height,int fx,int fy,int tox,int toy,int st,int t,int p){
55 | super(context);
56 |
57 | this.fromX=fx;
58 | this.fromY=fy;
59 | this.toX=tox;
60 | this.toY=toy;
61 | this.startTime=st;
62 | this.time=t;
63 |
64 | this.path=p;
65 |
66 | width=_width;
67 | height=_height;
68 |
69 | mcontext=context;
70 |
71 | this.setBackgroundColor(0xaaF8E097);
72 | // this.layout(fx,fy,fx+width,fy+height);
73 | this.setWidth(width);
74 | this.setHeight(height);
75 |
76 | //this.setWidth(80*441/160);
77 | //this.setHeight(40*441/160);//40dp*441ppi/160 px //setWidth()和后面getX()得到的也都是像素pixels,所以这里也用像素
78 |
79 |
80 | //this.start();
81 |
82 |
83 | }
84 |
85 | //继承的已有setVisibility(0)方法,getTranslationX(),getX()方法,
86 |
87 | public void start(ConstraintLayout layout){
88 | //
89 | // TranslateAnimation ta=new TranslateAnimation(fromX,toX,fromY,toY);
90 | // ta.setDuration(time);//动画时长 ms
91 | // ta.setStartOffset(startTime);//延时
92 | // //ta.setFillBefore(false);//动画结束时停在第一帧
93 | // //ta.setFillAfter(false);
94 | // /* final LinearLayout mlayout=layout;
95 | // EachButton eachButton=this;*/
96 | // //setStateValue(this,layout);
97 | // //this.setVisibility(INVISIBLE);
98 | // LinearInterpolator lin = new LinearInterpolator();//匀速运动
99 | // ta.setInterpolator(lin);
100 | //
101 | // layout=mlayout;
102 | //
103 | //
104 | // //setState(this,ta);
105 | // setStateValue(this);
106 | // layout.addView(this);//把addView放到onAnimationStart里面加载不出来
107 | //
108 | //
109 | // this.startAnimation(ta);//自动启动动画
110 | // //layout.removeView(this);
111 |
112 | //translateAnimation是表面呈现的移动,但布局没变,animator会随着变,方便获得移动中的位置
113 | mlayout=layout;
114 | //layout.addView(this);
115 | //ObjectAnimator.ofFloat(this, "translationY", fromY, toY).setDuration(time).setStartDelay(startTime);
116 | Path path=new Path();
117 | path.moveTo(fromX,fromY);//开始
118 | path.lineTo(toX,toY);//结束
119 | animator=ObjectAnimator.ofFloat(this,
120 | Property.of(LandEachButton.class,Float.class,"translationX"),
121 | Property.of(LandEachButton.class,Float.class,"translationY"),
122 | path);
123 | animator.setDuration(time);
124 | animator.setStartDelay(startTime);
125 |
126 | //animator.pause();
127 |
128 | LinearInterpolator lin = new LinearInterpolator();//匀速运动
129 | animator.setInterpolator(lin);
130 |
131 | final LandEachButton eachButton=this;
132 | animator.addListener(new Animator.AnimatorListener() {
133 | @Override
134 | public void onAnimationStart(Animator animation) {
135 | mlayout.addView(eachButton);
136 | }
137 |
138 | @Override
139 | public void onAnimationEnd(Animator animation) {
140 | mlayout.removeView(eachButton);
141 |
142 | if(eachButton.state) {
143 | View view = LayoutInflater.from(mcontext).inflate(R.layout.toast_land, null);
144 | TextView textView = view.findViewById(R.id.textView);
145 | textView.setText("miss");
146 | //textView.setTextColor(Color.parseColor("#909090"));
147 | //textView.setTextColor(getResources().getColor(R.color.colorGray));
148 | //Toast toast=new Toast(mcontext);
149 | Toast toast = FourGameActivity.toast;//方便被activity1里面新的点击替代,如果是新的可能替代不了
150 | toast.setView(view);
151 | toast.setDuration(Toast.LENGTH_SHORT);
152 |
153 | /*
154 | ObjectAnimator textAnimator=ObjectAnimator
155 | .ofFloat(textView,"translationY", textView.getY(), textView.getY()+200)
156 | .setDuration(1000);*/
157 | ObjectAnimator.ofArgb(textView, "textColor",
158 | Color.parseColor("#ff333333"),
159 | Color.parseColor("#00333333"))
160 | .setDuration(1000)
161 | .start();
162 | toast.show();
163 |
164 | FourGameActivity.buttons.get(eachButton.path).remove(0);
165 | FourGameActivity.missTimes+=1;
166 |
167 | if((FourGameActivity.buttons.get(0).size()+FourGameActivity.buttons.get(1).size()+
168 | FourGameActivity.buttons.get(2).size()+FourGameActivity.buttons.get(3).size()==0)&&
169 | FourGameActivity.activityState){
170 | final Intent iintent = new Intent(mcontext, ResultActivity.class);
171 | iintent.putExtra("wholeScore",FourGameActivity.wholeScore);
172 | iintent.putExtra("resultScore",FourGameActivity.resultScore);
173 | iintent.putExtra("bestTimes",FourGameActivity.bestTimes);
174 | iintent.putExtra("goodTimes",FourGameActivity.goodTimes);
175 | iintent.putExtra("missTimes",FourGameActivity.missTimes);
176 | TimerTask task = new TimerTask(){
177 | public void run(){
178 | mcontext.startActivity(iintent);
179 | }
180 | };
181 | Timer timer = new Timer();
182 | timer.schedule(task, 2000);
183 |
184 | }
185 |
186 | }
187 |
188 | }
189 |
190 | @Override
191 | public void onAnimationCancel(Animator animation) {
192 |
193 | }
194 |
195 | @Override
196 | public void onAnimationRepeat(Animator animation) {
197 |
198 | }
199 | });
200 | // animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
201 | // @Override
202 | // public void onAnimationUpdate(ValueAnimator animation) {
203 | // eachButton.setWidth(width+(int)animation.getCurrentPlayTime()/time*(endWidth-width));
204 | // eachButton.setWidth(height+(int)animation.getCurrentPlayTime()/time*(endHeight-height));
205 | // }
206 | // });
207 | animator.start();
208 | /*
209 | layout=mlayout;
210 | layout.addView(this);
211 | final EachButton eachButton=this;
212 | this.animate().translationY(toY)
213 | .setDuration(time).setStartDelay(startTime)
214 | .withEndAction(new Runnable() {
215 | @Override
216 | public void run() {
217 | layout.removeView(eachButton);
218 | }
219 | });
220 | */
221 | }
222 |
223 |
224 |
225 | /*
226 | public void viewRemoveButton(ConstraintLayout mlayout){
227 | mlayout.removeView(this);
228 | }
229 | */
230 |
231 | /*
232 | public void setState(final EachButton eachButton,TranslateAnimation ta){
233 |
234 | ta.setAnimationListener(new Animation.AnimationListener() {
235 |
236 | @Override
237 | public void onAnimationStart(Animation animation) {
238 | //layout.addView(eachButton);
239 | Log.d("state","here");
240 | //eachButton.setVisibility(VISIBLE);
241 |
242 | }
243 |
244 | @Override
245 | public void onAnimationEnd(Animation animation) {
246 | //Log.d("state","there");
247 | //eachButton.setVisibility(INVISIBLE);
248 | mlayout.removeView(eachButton);
249 | eachButton.state=false;
250 |
251 | View view =LayoutInflater.from(mcontext).inflate(R.layout.toast, null);
252 | TextView textView=view.findViewById(R.id.textView);
253 | textView.setText("miss");
254 | //textView.setTextColor(Color.parseColor("#909090"));
255 | textView.setTextColor(getResources().getColor(R.color.colorGray));
256 | Toast toast=new Toast(mcontext);
257 | toast.setView(view);
258 | toast.setDuration(Toast.LENGTH_SHORT);
259 | toast.show();
260 |
261 | Activity1.buttons.remove(0);
262 |
263 |
264 | }
265 |
266 | @Override
267 | public void onAnimationRepeat(Animation animation) {
268 |
269 | }
270 | });
271 |
272 | this.addOnLayoutChangeListener(new OnLayoutChangeListener() {
273 | @Override
274 | public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
275 | Toast.makeText(getContext(),top+"",Toast.LENGTH_SHORT).show();
276 | }
277 | });
278 |
279 |
280 | }
281 | */
282 |
283 | /*
284 | public void setStateValue(final EachButton eachButton){
285 |
286 |
287 | ValueAnimator valueAnimator= ValueAnimator.ofInt(eachButton.fromY,eachButton.toY);
288 | valueAnimator.setDuration(eachButton.time);
289 | valueAnimator.setStartDelay(eachButton.startTime);
290 |
291 | valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
292 | @Override
293 | public void onAnimationUpdate(ValueAnimator animation) {
294 | int curValue = (int)animation.getAnimatedValue();
295 | //layout(left,top,right,bottom)
296 | eachButton.layout(eachButton.fromX,curValue,eachButton.fromX+150,curValue+100);
297 | //if(curValue==1)
298 | //linearLayout.addView(eachButton);
299 | //eachButton.setVisibility(VISIBLE);
300 | if(curValue==eachButton.toY)
301 | //eachButton.setVisibility(INVISIBLE);
302 | mlayout.removeView(eachButton);
303 | }
304 | });
305 | valueAnimator.start();
306 |
307 | }
308 | */
309 |
310 |
311 |
312 |
313 | }
314 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/free/Classes/MP3ToWav.java:
--------------------------------------------------------------------------------
1 | //package com.example.free;
2 | //
3 | //
4 | //
5 | //import java.io.File;
6 | //import java.io.IOException;
7 | //import java.net.MalformedURLException;
8 | //import java.net.URL;
9 | //
10 | //import javax.sound.sampled.AudioFileFormat;
11 | //import javax.sound.sampled.AudioFormat;
12 | //import javax.sound.sampled.AudioInputStream;
13 | //import javax.sound.sampled.AudioSystem;
14 | //import javax.sound.sampled.UnsupportedAudioFileException;
15 | //
16 | //
17 | //
18 | ///*import org.json.JSONObject;
19 | //
20 | //import com.baidu.aip.speech.AipSpeech;*/
21 | //
22 | //public class MP3ToWav {
23 | //
24 | // public static File byteToWav(URL sourceURL, String targetPath) {
25 | //
26 | // File file=new File(targetPath);
27 | //
28 | // try (final AudioInputStream sourceAIS = AudioSystem.getAudioInputStream(sourceURL)) {
29 | // //得到输入流
30 | //
31 | // AudioFormat sourceFormat = sourceAIS.getFormat();//原格式
32 | //
33 | // //需要再从mp3转mp3一次,再从mp3转wav,,直接从mp3转wav报错。。
34 | // // 设置MP3的语音格式,并设置16bit
35 | // AudioFormat mp3tFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, sourceFormat.getSampleRate(), 16, sourceFormat.getChannels(), sourceFormat.getChannels() * 2, sourceFormat.getSampleRate(), false);
36 | // //sourceFormat.getSampleRate()每秒的样本数,16每个样本中的位数(两个字节),sourceFormat.getChannels()声道数,每帧的字节数,每秒的帧数,false是否以 big-endian 字节顺序存储单个样本中的数据
37 | //
38 | // // 设置wav的音频格式
39 | // AudioFormat pcmFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 16000, 16, 1, 2, 16000, false);
40 | // try (
41 | // // 先通过MP3转一次,使音频流能的格式完整,,mp3格式转mp3格式,得到完整mp3格式的输入流
42 | // final AudioInputStream mp3AIS = AudioSystem.getAudioInputStream(mp3tFormat, sourceAIS);
43 | //
44 | // // 转成需要的流,mp3格式转wav格式,得到输入流
45 | // final AudioInputStream pcmAIS = AudioSystem.getAudioInputStream(pcmFormat, mp3AIS);
46 | // ) {
47 | // // 根据路径生成wav文件,输入流转文件。
48 | // AudioSystem.write(pcmAIS, AudioFileFormat.Type.WAVE, file);
49 | // }
50 | //
51 | // return file;
52 | // } catch (IOException e) {
53 | // //System.out.println("文件转换异常:" + e.getMessage());
54 | // return null;
55 | // } catch (UnsupportedAudioFileException e) {
56 | // //System.out.println("文件转换异常:" + e.getMessage());//could not get audio input stream from input stream
57 | //
58 | // return null;
59 | // }
60 | // }
61 | //
62 | //
63 | // public static File getWav(String filePath) {
64 | // String fileURL = "file://"+filePath;//url为"file://"开头
65 | // String targetPath = "1.wav";
66 | // try {
67 | // return byteToWav(new URL(fileURL),targetPath);
68 | // } catch (MalformedURLException e) {
69 | // // TODO Auto-generated catch block
70 | // e.printStackTrace();
71 | // }
72 | // return null;
73 | //
74 | // }
75 | //}
76 | //
77 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/free/Classes/MP3ToWav1.java:
--------------------------------------------------------------------------------
1 | //package com.example.free;
2 | //
3 | //import android.media.MediaCodec;
4 | //import android.media.MediaExtractor;
5 | //import android.media.MediaFormat;
6 | //import android.text.TextUtils;
7 | //
8 | //import java.io.FileInputStream;
9 | //
10 | //public class MP3ToWav1 {
11 | //
12 | // public static void main(String args[]) {
13 | // String fileURL = "file://G:/app/code/music.mp3";//url为"file://"开头
14 | // String targetPath = "G:/app/code/G.wav";
15 | // MediaExtractor mediaExtractor = new MediaExtractor();
16 | // MediaFormat mediaFormat = null;
17 | // MediaCodec mediaCodec = null;
18 | //
19 | //
20 | // }
21 | //
22 | // /**
23 | // * 将音乐文件解码
24 | // *
25 | // * @param musicFileUrl 源文件路径
26 | // * @param decodeFileUrl 解码文件路径
27 | // * @param startMicroseconds 开始时间 微秒
28 | // * @param endMicroseconds 结束时间 微秒
29 | //// * @param decodeOperateInterface 解码过程回调
30 | // */
31 | // private boolean decodeMusicFile(String musicFileUrl, String decodeFileUrl,
32 | // long startMicroseconds, long endMicroseconds
33 | //// , DecodeOperateInterface decodeOperateInterface
34 | // ) {
35 | //
36 | // //采样率,声道数,时长,音频文件类型
37 | // int sampleRate = 0;
38 | // int channelCount = 0;
39 | // long duration = 0;
40 | // String mime = null;
41 | //
42 | // //MediaExtractor, MediaFormat, MediaCodec
43 | // MediaExtractor mediaExtractor = new MediaExtractor();
44 | // MediaFormat mediaFormat = null;
45 | // MediaCodec mediaCodec = null;
46 | //
47 | // //给媒体信息提取器设置源音频文件路径
48 | // try {
49 | // mediaExtractor.setDataSource(musicFileUrl);
50 | // }catch (Exception ex){
51 | // ex.printStackTrace();
52 | // try {
53 | // mediaExtractor.setDataSource(new FileInputStream(musicFileUrl).getFD());
54 | // } catch (Exception e) {
55 | // e.printStackTrace();
56 | //// LogUtil.e("设置解码音频文件路径错误");
57 | // }
58 | // }
59 | //
60 | // //获取音频格式轨信息
61 | // mediaFormat = mediaExtractor.getTrackFormat(0);
62 | //
63 | // //从音频格式轨信息中读取 采样率,声道数,时长,音频文件类型
64 | // sampleRate = mediaFormat.containsKey(MediaFormat.KEY_SAMPLE_RATE) ? mediaFormat.getInteger(
65 | // MediaFormat.KEY_SAMPLE_RATE) : 44100;
66 | // channelCount = mediaFormat.containsKey(MediaFormat.KEY_CHANNEL_COUNT) ? mediaFormat.getInteger(
67 | // MediaFormat.KEY_CHANNEL_COUNT) : 1;
68 | // duration = mediaFormat.containsKey(MediaFormat.KEY_DURATION) ? mediaFormat.getLong(
69 | // MediaFormat.KEY_DURATION) : 0;
70 | // mime = mediaFormat.containsKey(MediaFormat.KEY_MIME) ? mediaFormat.getString(MediaFormat.KEY_MIME)
71 | // : "";
72 | //
73 | //// LogUtil.i("歌曲信息Track info: mime:"
74 | //// + mime
75 | //// + " 采样率sampleRate:"
76 | //// + sampleRate
77 | //// + " channels:"
78 | //// + channelCount
79 | //// + " duration:"
80 | //// + duration);
81 | //
82 | // if (TextUtils.isEmpty(mime) || !mime.startsWith("audio/")) {
83 | //// LogUtil.e("解码文件不是音频文件mime:" + mime);
84 | // return false;
85 | // }
86 | //
87 | // if (mime.equals("audio/ffmpeg")) {
88 | // mime = "audio/mpeg";
89 | // mediaFormat.setString(MediaFormat.KEY_MIME, mime);
90 | // }
91 | //
92 | // if (duration <= 0) {
93 | //// LogUtil.e("音频文件duration为" + duration);
94 | // return false;
95 | // }
96 | //
97 | // //解码的开始时间和结束时间
98 | // startMicroseconds = Math.max(startMicroseconds, 0);
99 | // endMicroseconds = endMicroseconds < 0 ? duration : endMicroseconds;
100 | // endMicroseconds = Math.min(endMicroseconds, duration);
101 | //
102 | // if (startMicroseconds >= endMicroseconds) {
103 | // return false;
104 | // }
105 | //
106 | // //创建一个解码器
107 | // try {
108 | // mediaCodec = MediaCodec.createDecoderByType(mime);
109 | //
110 | // mediaCodec.configure(mediaFormat, null, null, 0);
111 | // } catch (Exception e) {
112 | //// LogUtil.e("解码器configure出错");
113 | // return false;
114 | // }
115 | //
116 | // //得到输出PCM文件的路径
117 | // decodeFileUrl = decodeFileUrl.substring(0, decodeFileUrl.lastIndexOf("."));
118 | // String pcmFilePath = decodeFileUrl + ".pcm";
119 | //
120 | // //后续解码操作
121 | // getDecodeData(mediaExtractor, mediaCodec, pcmFilePath, sampleRate, channelCount,
122 | // startMicroseconds, endMicroseconds, decodeOperateInterface);
123 | //
124 | // return true;
125 | // }
126 | //}
127 | //
128 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/free/Classes/Music.java:
--------------------------------------------------------------------------------
1 | package com.example.free.Classes;
2 |
3 | public class Music {
4 |
5 | private String name="";
6 | private String path="";
7 | private long size=0;
8 | private long time=0;
9 |
10 | public Music(String _name,String _path,long _size,long _time){
11 | name=_name;
12 | path=_path;
13 | size=_size;
14 | time=_time;
15 | }
16 |
17 | public String getName(){
18 | return name;
19 | }
20 |
21 | public String getPath(){
22 | return path;
23 | }
24 | public long getSize(){
25 | return size;
26 | }
27 | public long getTime(){
28 | return time;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/free/Classes/MusicAdapter.java:
--------------------------------------------------------------------------------
1 | package com.example.free.Classes;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.TextView;
9 |
10 | import androidx.annotation.NonNull;
11 | import androidx.recyclerview.widget.RecyclerView;
12 |
13 | import com.example.free.ChoiceActivity;
14 | import com.example.free.GameActivity;
15 | import com.example.free.OriginChoiceActivity;
16 | import com.example.free.R;
17 |
18 | import java.util.List;
19 |
20 |
21 | public class MusicAdapter extends RecyclerView.Adapter {
22 |
23 | private List musicList;
24 |
25 | //构造函数别忘了
26 | public MusicAdapter(List _musicList) {
27 | musicList=_musicList;
28 | }
29 |
30 | @NonNull
31 | @Override
32 | public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
33 | View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.music_item,parent,false);
34 | //得到每一项的样式view,不继承parent
35 | final ViewHolder viewHolder=new ViewHolder(view);
36 | final Context context=parent.getContext();
37 | view.setOnClickListener(new View.OnClickListener() {
38 | @Override
39 | public void onClick(View v) {
40 | int position=viewHolder.getAdapterPosition();
41 | Music music=musicList.get(position);
42 | String musicPath=music.getPath();
43 | long musicSize=music.getSize();
44 | long musicTime=music.getTime();
45 | //Intent intent=new Intent(context,MusicActivity.class);
46 | //Intent intent=new Intent(context, ChoiceActivity.class);
47 | Intent intent=new Intent(context, OriginChoiceActivity.class);
48 | intent.putExtra("musicPath",musicPath);
49 | intent.putExtra("musicSize", musicSize);
50 | intent.putExtra("musicTime",musicTime);
51 | context.startActivity(intent);
52 | }
53 | });
54 |
55 | return viewHolder;
56 | }
57 |
58 | @Override
59 | public void onBindViewHolder(@NonNull ViewHolder viewHolder, int position) {
60 | Music music=musicList.get(position);
61 | viewHolder.textView.setText(music.getName());
62 | }
63 |
64 | @Override
65 | public int getItemCount() {
66 | return musicList.size();
67 | }
68 |
69 |
70 | class ViewHolder extends RecyclerView.ViewHolder{
71 | //ViewHolder在adapter新建时储存控件实例/样式,这样在后面就不用一直findViewById查找
72 |
73 | TextView textView;
74 |
75 | ViewHolder(View view){
76 | super(view);
77 | textView=view.findViewById(R.id.textView);
78 | }
79 | }
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/free/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.free;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.appcompat.app.AppCompatActivity;
5 | import androidx.core.app.ActivityCompat;
6 | import androidx.core.content.ContextCompat;
7 |
8 | import android.Manifest;
9 | import android.content.Intent;
10 | import android.content.pm.PackageManager;
11 | import android.os.Bundle;
12 | import android.os.Handler;
13 | import android.os.Message;
14 | import android.view.View;
15 | import android.view.animation.AnimationUtils;
16 | import android.view.animation.TranslateAnimation;
17 | import android.widget.Button;
18 | import android.widget.LinearLayout;
19 | import android.widget.Toast;
20 |
21 | import com.example.free.Classes.BaseActivity;
22 |
23 | public class MainActivity extends AppCompatActivity {
24 |
25 | Button location;
26 |
27 | @Override
28 | protected void onCreate(Bundle savedInstanceState) {
29 | super.onCreate(savedInstanceState);
30 | setContentView(R.layout.activity_main);
31 |
32 | // Button button=findViewById(R.id.button);
33 | // button.setOnClickListener(new View.OnClickListener() {
34 | // @Override
35 | // public void onClick(View v) {
36 | // //以自身为坐标点 (x轴的起点(与现在位置的差值),结束点,y轴的起点,结束点)
37 | // TranslateAnimation ta=new TranslateAnimation(0,200,0,300);
38 | // ta.setDuration(2000);//时长 ms
39 | // v.startAnimation(ta);//自动启动动画
40 | // }
41 | // });
42 |
43 |
44 | // Button button_startAnim=findViewById(R.id.button_startAnim);
45 | // button_startAnim.setOnClickListener(new View.OnClickListener() {
46 | // @Override
47 | // public void onClick(View v) {
48 | // v.startAnimation(AnimationUtils.loadAnimation(getApplicationContext(),+R.anim.anim));
49 | //
50 | // }
51 | // });
52 | //
53 | // Button remove=findViewById(R.id.remove);
54 | // remove.setOnClickListener(new View.OnClickListener() {
55 | // @Override
56 | // public void onClick(View v) {
57 | // LinearLayout ll=findViewById(R.id.content);
58 | // ll.removeView(findViewById(R.id.textView));//或者是int 即LinearLayout容器里面的第几个(index)
59 | // }
60 | // });
61 |
62 | // Button button_Activity1=findViewById(R.id.Activity1);
63 | // button_Activity1.setOnClickListener(new View.OnClickListener() {
64 | // @Override
65 | // public void onClick(View v) {
66 | //
67 | // Intent intent=new Intent(MainActivity.this, Activity1.class);
68 | // startActivity(intent);
69 | // }
70 | // });
71 |
72 | ///*
73 | // Timer timer=new Timer();
74 | // TextView textView=findViewById(R.id.textView);
75 | // timer.schedule(new Task((View)textView),2000);*/
76 | // new Handler(new Handler.Callback() {
77 | // @Override
78 | // public boolean handleMessage(@NonNull Message msg) {
79 | // findViewById(R.id.textView).startAnimation(AnimationUtils.loadAnimation(getApplicationContext(),+R.anim.anim));
80 | // return false;
81 | // }
82 | // }).sendEmptyMessageDelayed(0,2000);
83 | ///*
84 | // new Handler().postDelayed(new Runnable() {
85 | // @Override
86 | // public void run() {
87 | // findViewById(R.id.textView).startAnimation(AnimationUtils.loadAnimation(getApplicationContext(),+R.anim.anim));
88 | // }
89 | // },2000);*/
90 | //
91 | // location=findViewById(R.id.location);
92 | //
93 | // location.setOnClickListener(new View.OnClickListener() {
94 | // @Override
95 | // public void onClick(View v) {
96 | // int[] xy=new int[2];
97 | // location.getLocationOnScreen(xy);
98 | // Toast.makeText(MainActivity.this,xy[1]+"",Toast.LENGTH_SHORT).show();
99 | // }
100 | // });
101 | //
102 | Button music=findViewById(R.id.music);
103 | music.setOnClickListener(new View.OnClickListener() {
104 | @Override
105 | public void onClick(View v) {
106 |
107 | if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
108 | != PackageManager.PERMISSION_GRANTED){
109 | //申请权限,名字与manifest里面的一致,1为请求码;需要重写onRequestPermissionsResult的得到申请权限的回调函数
110 | ActivityCompat.requestPermissions(MainActivity.this,new String[]{
111 | Manifest.permission.WRITE_EXTERNAL_STORAGE},1
112 | );
113 | //这里是需要先把文件读出来,再处理
114 | }
115 | else{
116 | // Intent intent=new Intent(MainActivity.this,MusicActivity.class);
117 | Intent intent=new Intent(MainActivity.this,MusicViewActivity.class);
118 | startActivity(intent);
119 | }
120 |
121 | }
122 | });
123 |
124 | Button exit=findViewById(R.id.exit);
125 | exit.setOnClickListener(new View.OnClickListener() {
126 | @Override
127 | public void onClick(View v) {
128 | finish();
129 | System.exit(0);
130 | }
131 | });
132 |
133 | //
134 | // Button force=findViewById(R.id.force);
135 | // force.setOnClickListener(new View.OnClickListener() {
136 | // @Override
137 | // public void onClick(View v) {
138 | // Intent intent=new Intent(MainActivity.this,ResultActivity.class);
139 | // startActivity(intent);
140 | // }
141 | // });
142 | //
143 | //
144 | //
145 | }
146 |
147 | @Override
148 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
149 | //grantResults是用户授权结果,只是接收结果给出反应,不是给出结果的过程
150 | //super.onRequestPermissionsResult(requestCode, permissions, grantResults);
151 | switch(requestCode){
152 | case 1://请求码,一个活动里可能处理多个权限请求,对应不同的请求码
153 | if(grantResults.length>0&&grantResults[0]==PackageManager.PERMISSION_GRANTED){
154 | Intent intent=new Intent(MainActivity.this,MusicViewActivity.class);
155 | startActivity(intent);
156 | }else{
157 | Toast.makeText(this,"you denied the permission",Toast.LENGTH_SHORT).show();
158 | finish();//拒绝时回到上一页面
159 | }
160 | break;
161 | default:
162 | }
163 | }
164 |
165 | //
166 | // /*
167 | // public void startAnimation(View v){
168 | // v.startAnimation(AnimationUtils.loadAnimation(getApplicationContext(),+R.anim.anim));
169 | // }*/
170 | //
171 | // /*
172 | // class Task extends TimerTask{
173 | // View v;
174 | // Task(View v){
175 | // this.v=v;
176 | // }
177 | // @Override
178 | // public void run() {
179 | // v.startAnimation(AnimationUtils.loadAnimation(getApplicationContext(),+R.anim.anim));
180 | // }
181 | // //Only the original thread that created a view hierarchy can touch its views.
182 | // //只有创建这个view的线程才能操作这个view,普通会认为是将view创建在非UI线程中才会出现这个错误。
183 | // }
184 | //*/
185 | }
186 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/free/Mp3Handle/FrameData.java:
--------------------------------------------------------------------------------
1 | package com.example.free.Mp3Handle;
2 |
3 | import java.util.Map;
4 |
5 | public class FrameData {//帧信息类
6 | private FrameHead frameHead;
7 | private byte[] bitData;
8 | private int bitSize;
9 |
10 | public FrameData(byte[] head) throws Exception {
11 | this.frameHead = new FrameData.FrameHead(head);
12 | this.bitSize = this.frameHead.getBitDataSize();
13 | }
14 |
15 | public void setBitData(byte[] data) {
16 | this.bitData = data;
17 | }
18 |
19 | public int getBitSize() {
20 | return this.bitSize;
21 | }
22 |
23 | public int getSampling() {
24 | return this.frameHead.sampling;
25 | }
26 |
27 | class FrameHead {
28 | /* 4字节(32位)数据 */
29 | /*
30 | * AAAAAAAA AAABBCCD EEEEFFGH IIJJKLMM 注意以上格式:将解释按照位操作数据 A 31-21 [11bit]
31 | * Frame sync帧同步 B 20-19 [2 bit] MPEG音频版本 (00 - MPEG Version 2.5) (01 -
32 | * 保留) (10 - MPEG Version 2) (11 - MPEG Version 1) C 18-17 [2 bit] 层描述
33 | * (00 - 保留) (01 - Layer III) (10 - Layer II) (11 - Layer I) D 16 [1
34 | * bit] 保护位 0意味着受CRC保护,帧头后面跟16位的CRC E 15-12 [4 bit] 比特率 F 11-10 [2 bit]
35 | * 采样频率 bits MPEG1 MPEG2 MPEG2.5 00 44100 22050 11025 01 48000 24000
36 | * 12000 10 32000 16000 8000 11 reserv reserv reserv G 9 [1 bit]
37 | * 意味着帧里包含padding位,仅当采样频率为44.1KHz时发生 H 8 [1 bit] 私有未知位 I 7-6 [2 bit]
38 | * 声道模式 (00 - 立体声) (01 - 联合立体声) (11 - 双通道) (11 - 单通道) J 5-4 [2 bit] 扩展模式
39 | * bit 强度立体声 MS立体声 00 关闭 关闭 01 开 关 10 关闭 开 11 开 开 K 3 [1 bit] 版权保护位 L 2
40 | * [1 bit] 是否拷贝 0=副本 1=原来的 M 1-0 [2 bit] 重点位 (00 - 不重视) (01 - 50/15毫秒)
41 | * (10 - 保留) (11 - 国际电报电话咨询委员会J.17)
42 | */
43 | private String MPEGVersion;// MPEG版本
44 | private boolean protectionBit;// true 代表别保护 帧头后有16bit CRC
45 | private int bitrate;// 比特率
46 | private int sampling;// 采样率
47 | private boolean paddingBit;//
48 | private String channelMode;// 声道模式
49 | private int bitDataSize;// 实际声音数据大小(字节)
50 |
51 | public FrameHead(byte[] head) throws Exception {
52 | // System.out.println(head.toString());
53 | // for(int i=0;i>>3
63 | this.protectionBit = this.getProtectionBitByBit(head[1]);//CRC校验,第16位,第二个字节byte[1],b&00000001
64 | this.bitrate = this.getBitrateByBit(head[2]);//比特率(码率),第17到20位,第三个字节byte[2],b&11110000>>>4
65 | // int getSampling=this.getSamplingByBit(head[2]);
66 | // if(getSampling>0)this.sampling = getSampling;
67 | // //有的帧采样率无值(-1)(怀疑被压缩)的继承上一个,-1的时候比特率都是96000,不能这样,压缩的,getBit会出错比特率=采样率*12*声道数
68 | this.sampling=this.getSamplingByBit(head[2]);//采样率(码率),第21到22位,第三个字节byte[2],b&00001100>>>2
69 | this.paddingBit = this.getPaddingBitByBit(head[2]);//是否填充空白字,第23位,第三个字节byte[2],b&00000010
70 | this.channelMode = this.getChannelModeByBit(head[3]);//声道模式,第25到26位,第四个字节byte[3],b&11110000>>>4
71 | this.bitDataSize = this.getBitDataSizeByBit();
72 |
73 | // System.out.println("bitrate:"+bitrate+" sampling:"+sampling+" channelMode:"+channelMode+" bitDataSize:"+bitDataSize);
74 |
75 | }
76 |
77 | public int getBitDataSize() {
78 | return bitDataSize;
79 | }
80 |
81 | public int getBitrate() {
82 | return bitrate;
83 | }
84 |
85 | public String getChannelMode() {
86 | return channelMode;
87 | }
88 |
89 | public String getMPEGVersion() {
90 | return MPEGVersion;
91 | }
92 |
93 | public boolean isPaddingBit() {
94 | return paddingBit;
95 | }
96 |
97 | public boolean isProtectionBit() {
98 | return protectionBit;
99 | }
100 |
101 | public int getSampling() {
102 | return sampling;
103 | }
104 |
105 | // 所有的位操作在private方法进行
106 | private String getMPEGVersionByBit(byte b) {//12到13位,第二个字节byte[1]
107 | b = (byte) ((b & 24) >>> 3);// b&00011000
108 | if (b == 0)
109 | return "MPEG2.5";
110 | else if (b == 1)
111 | return "保留";
112 | else if (b == 2)
113 | return "MPEG2";
114 | else if (b == 3)
115 | return "MPEG1";
116 | else
117 | return "ERROR";
118 | }
119 |
120 | private boolean getProtectionBitByBit(byte b) {//
121 | b = (byte) (b & 1);// b&00000001
122 | if (b == 0)
123 | return true;
124 | else
125 | return false;
126 | }
127 |
128 | private int getBitrateByBit(byte b) {//17到20位
129 | /*
130 | * 0000 free free free free free free 0001 32 32 32 32 32 8 (8) 0010
131 | * 64 48 40 64 48 16 (16) 0011 96 56 48 96 56 24 (24) 0100 128 64 56
132 | * 128 64 32 (32) 0101 160 80 64 160 80 64 (40) 0110 192 96 80 192
133 | * 96 80 (48) 0111 224 112 96 224 112 56 (56) 1000 256 128 112 256
134 | * 128 64 (64) 1001 288 160 128 288 160 128 (80) 1010 320 192 160
135 | * 320 192 160 (96) 1011 352 224 192 352 224 112 (112) 1100 384 256
136 | * 224 384 256 128 (128) 1101 416 320 256 416 320 256 (144) 1110 448
137 | * 384 320 448 384 320 (160) 1111 bad bad bad bad bad bad
138 | */
139 | b = (byte) ((b & 240) >>> 4);// b&11110000
140 | if (b == 0) {
141 | return 0;
142 | } else if (b == 1)
143 | return 8000;
144 | else if (b == 2)
145 | return 16000;
146 | else if (b == 3)
147 | return 24000;
148 | else if (b == 4)
149 | return 32000;
150 | else if (b == 5)
151 | return 40000;
152 | else if (b == 6)
153 | return 48000;
154 | else if (b == 7)
155 | return 56000;
156 | else if (b == 8)
157 | return 64000;
158 | else if (b == 9)
159 | return 80000;
160 | else if (b == 10)
161 | return 96000;
162 | else if (b == 11)
163 | return 112000;
164 | else if (b == 12)
165 | return 128000;
166 | else if (b == 13)
167 | return 144000;
168 | else if (b == 14)
169 | return 160000;
170 | else if (b == 15)
171 | return -1;
172 | else
173 | return -1;
174 |
175 | }
176 |
177 | private int getSamplingByBit(byte b) {
178 | /*
179 | * bits MPEG1 MPEG2 MPEG2.5 00 44100 22050 11025 01 48000 24000
180 | * 12000 10 32000 16000 8000 11 reserv reserv reserv
181 | */
182 | b = (byte) ((b & 12) >>> 2);// 00001100
183 | if (b == 0) {
184 | if (this.MPEGVersion.equals("MPEG1"))
185 | return 44100;
186 | else if (this.MPEGVersion.equals("MPEG2"))
187 | return 22050;
188 | else if (this.MPEGVersion.equals("MPEG2.5"))
189 | return 11025;
190 | else
191 | return -1;
192 | } else if (b == 1) {
193 | if (this.MPEGVersion.equals("MPEG1"))
194 | return 48000;
195 | else if (this.MPEGVersion.equals("MPEG2"))
196 | return 24000;
197 | else if (this.MPEGVersion.equals("MPEG2.5"))
198 | return 12000;
199 | else
200 | return -1;
201 | } else if (b == 2) {
202 | if (this.MPEGVersion.equals("MPEG1"))
203 | return 32000;
204 | else if (this.MPEGVersion.equals("MPEG2"))
205 | return 16000;
206 | else if (this.MPEGVersion.equals("MPEG2.5"))
207 | return 8000;
208 | else
209 | return -1;
210 | } else
211 | return -1;
212 | }
213 |
214 | private boolean getPaddingBitByBit(byte b) {
215 | b = (byte) ((b & 2) >>> 1);// 00000010
216 | if (b == 1 && this.sampling == 44100)
217 | return true;// ??
218 | else
219 | return false;
220 | }
221 |
222 | private String getChannelModeByBit(byte b) {
223 | /* (00 - 立体声) (01 - 联合立体声) (11 - 双通道) (11 - 单通道) */
224 | b = (byte) ((b & 192) >>> 6);// 11000000
225 | if (b == 0)
226 | return "立体声";
227 | else if (b == 1)
228 | return "联合立体声";
229 | else if (b == 2)
230 | return "双声道";
231 | else if (b == 3)
232 | return "单声道";
233 | else
234 | return "ERROR";
235 | }
236 |
237 | private int getBitDataSizeByBit() {
238 | // (((MpegVersion == MPEG1 ? 144 : 72) * Bitrate) / SamplingRate) +
239 | // PaddingBit
240 |
241 | /*帧长度是压缩时每一帧的长度, 包括帧头。这里采用LayerIII,,不同layer编码器不一样,表示层
242 | * LayerI空位长4字节,使用公式:帧长度(字节) = (( 每帧采样数/ 8 * 比特率 ) / 采样频率 ) + 填充 * 4
243 | * LayerII和LayerIII使用公式:帧长度(字节)= (( 每帧采样数/ 8 * 比特率 ) / 采样频率 ) + 填充
244 | * 每帧采样数:MPEG1 MPEG2 MPEG2.5
245 | * Layer2 1152 1152 1152
246 | * Layer3 1152 576 576
247 | *
248 | * 第一帧帧头 100 -65 -63 -17
249 | * 二进制源码1100100 11000001 10111111 10010001
250 | * 补码(最高位不变取反加一)1100100 10111111 11000001 11101111
251 | * 第12到13位:版本,其值为11 ->MPEG 1 第14到15位:层,其值为01->Layer 3
252 | * 帧长度(字节)= ( 每帧采样数/ 采样频率 )*比特率 /8 + 填充
253 | * 帧长度*8/采样率
254 | * */
255 | //System.out.println(this.MPEGVersion);
256 |
257 | //已除以8,单位是字节
258 |
259 | int size =0;
260 | if(bitrate<=0)
261 | if (sampling > 0)
262 | size = (int) ((this.MPEGVersion.equals("MPEG1") ? 144 : 72) * 128000 / this.sampling);
263 | else
264 | size = (int) ((this.MPEGVersion.equals("MPEG1") ? 144 : 72) * 128000 / 44100);//1152/8*采样率/441000
265 | else{
266 | if (sampling > 0)
267 | size = (int) ((this.MPEGVersion.equals("MPEG1") ? 144 : 72) * this.bitrate / this.sampling);
268 | else
269 | size = (int) ((this.MPEGVersion.equals("MPEG1") ? 144 : 72) * this.bitrate / 44100);//1152/8*采样率/441000
270 | }
271 | if (this.paddingBit)//是否填充空白字
272 | return size + 1;
273 | else
274 | return size;
275 | }
276 |
277 | }// inner Class
278 |
279 | }// outer Class
280 |
281 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/free/Mp3Handle/Mp3FileReader.java:
--------------------------------------------------------------------------------
1 | package com.example.free.Mp3Handle;
2 |
3 |
4 | import java.io.BufferedInputStream;
5 | import java.io.File;
6 | import java.io.FileInputStream;
7 | import java.io.FileNotFoundException;
8 | import java.io.IOException;
9 | import java.util.ArrayList;
10 | import java.util.HashMap;
11 | import java.util.LinkedList;
12 | import java.util.List;
13 | import java.util.Map;
14 |
15 | import com.example.free.Classes.HandleData;
16 | import com.example.free.Mp3Handle.FrameData;
17 |
18 | //import iface.PrivateInfo;
19 | //import iface.PublicInfo;
20 |
21 | public class Mp3FileReader {
22 | private static Map style = new HashMap();
23 |
24 | private Mp3FileReader.SongInfo songInfo;
25 | private Mp3FileReader.DataInfo dataInfo;
26 |
27 | private List frameList;//数据内容
28 | byte[] data = null;
29 | // int[][] data1 = null;
30 | int dataLength = 0;
31 | int sampling = 44100;
32 | ArrayList allTime=new ArrayList<>();
33 | //ArrayList samplings=new ArrayList<>();
34 | //ArrayList initTimes=new ArrayList<>();
35 | final int EACHHANDLE=1280;//byte,10240bit 1帧120*2byte,1920bit,十帧一处理
36 |
37 | /**
38 | * 主要分为开头音频信息,标签(标签头 标签内容组),数据(帧头,帧内容组),结尾歌曲信息
39 | **/
40 |
41 | public Mp3FileReader(String filename) {
42 |
43 | File file = new File(filename);
44 | byte[] bufLast = new byte[128];// 结尾128字节
45 | byte[] bufFront = new byte[10];// 开头10字节
46 | byte[] bufFrame = null;// 中间数据帧
47 | byte[] headLabel = null;// 标签帧(未知长度和帧数)
48 | try {
49 | FileInputStream is = new FileInputStream(file);
50 | BufferedInputStream bis = new BufferedInputStream(is);
51 | try {
52 | System.out.println("here is label head");
53 | is.read(bufFront, 0, 10);
54 | this.dataInfo = new Mp3FileReader.DataInfo(bufFront);//标签头 版本号 标签大小之类的
55 |
56 | System.out.println("here is label inner");
57 | headLabel = new byte[this.dataInfo.getSize()];
58 | is.read(headLabel, 0, headLabel.length);//往下读标签长度的字节,得到标签内容,赋值给headLabel
59 | this.ID3ByHeadList(headLabel);//得到标签信息(标题 作者等)return Map(name,data)
60 |
61 | System.out.println("here is data");
62 | bufFrame = new byte[(int) (file.length() - 128 - 10 - headLabel.length)];//总长度-结尾128-标签头10-标签,,数据不太符合
63 | is.read(bufFrame, 0, bufFrame.length);
64 | this.analyseFrame(bufFrame);//一帧一帧读,赋值给frameList
65 |
66 | System.out.println("here is last");
67 | is.skip(file.length() - (128 + 10 + headLabel.length + bufFrame.length));//文本流跳过中间可能冗余的其他信息???
68 | is.read(bufLast, 0, 128);//获取结尾歌曲信息
69 | this.songInfo = new Mp3FileReader.SongInfo(bufLast);
70 | System.out.println("title:"+songInfo.title+" artist:"+songInfo.artist);
71 |
72 | // int[] dataResult=getData();
73 | // int n=dataResult.length/EACHHANDLE/8+1;
74 | // for(int i=0;i ID3ByHeadList(byte[] buf) {//得到标签帧内容 标题 作者等
273 | /*
274 | * 标签帧: | 数据名 | 数据长度 | 标记 | [真实数据] | .....
275 | */
276 | Map map = new HashMap();
277 | int pix = 0;
278 | byte[] head;// 4 标识帧,说明其内容 TIT2表示内容为这首歌的标题,TPE1作者 TALB专辑 TRCK因规格是 TYER年代
279 | byte[] size;// 4 帧内容大小(只包含内容的大小)
280 | byte[] flag;// 2 存放标志 (c只读 i压缩 j加密等)
281 | int dataLeng = 0;
282 | byte[] dataBuf;// n
283 |
284 | System.out.println("buf.length:" + buf.length);//230
285 | for (; pix < buf.length; ) {//循环几组 标题组 作者组等
286 | head = new byte[4];
287 | size = new byte[4];
288 | flag = new byte[2];
289 | System.arraycopy(buf, pix, head, 0, 4);
290 | pix = pix + 4;
291 | System.arraycopy(buf, pix, size, 0, 4);
292 | pix = pix + 4;
293 | System.arraycopy(buf, pix, flag, 0, 2);
294 | pix = pix + 2;
295 | dataLeng = getSizeByByte(size);
296 | if (dataLeng <= 0)
297 | return map;
298 | System.out.println(dataLeng);
299 | dataBuf = new byte[dataLeng];
300 | dataLeng = dataLeng < buf.length - pix ? dataLeng : buf.length - pix;
301 | System.arraycopy(buf, pix, dataBuf, 0, dataLeng);
302 | pix = pix + dataLeng;
303 | map.put(new String(head), new String(dataBuf));
304 | // System.out.println(new String(head) + " \t| " + new String(dataBuf) + " \t| " + pix);
305 |
306 | }
307 |
308 | return map;
309 |
310 | }
311 |
312 | private void analyseFrame(byte[] frameByte) throws Exception {
313 | data = new byte[frameByte.length];
314 | int dataIndex = 0;
315 | frameList = new LinkedList();
316 | int pix = 0;
317 | int size = 0;
318 | byte[] frameHead;// 帧头 (四字节,各位bit包含 同步信息 CRC校验 版权 采样率 声道等信息)
319 | byte[] frameData;// 数据帧
320 | int countLength=0;
321 | int countSampling=0;
322 | int initTime=0;
323 | int initTimeAfter=0;
324 | //initTimes.add(0);
325 |
326 | for (; pix < frameByte.length; ) {//一帧一帧循环
327 | frameHead = new byte[4];//帧头信息,4字节
328 | System.arraycopy(frameByte, pix, frameHead, 0, 4);
329 | pix = pix + 4;
330 | if (pix >= frameByte.length)
331 | break;
332 | //if(pix==4){
333 | FrameData frame = new FrameData(frameHead);//帧信息类 里面只具体解析了帧头的信息,setBitData(byte[] data)数据是要外部传的
334 | size = frame.getBitSize();//大小 数据长度
335 |
336 | if (pix == 4) this.sampling = frame.getSampling();
337 | this.dataLength += frame.getBitSize();
338 |
339 |
340 | countLength+=size;
341 | countSampling+=size*sampling;
342 | initTimeAfter+=(int)(size*8/(sampling/1000.0));
343 |
344 | if(countLength>= EACHHANDLE){
345 | byte[] countData=new byte[countLength];
346 | System.arraycopy(frameByte, pix, countData, 0, countLength);
347 | int[] countDataAfter=changeData(countData);
348 | HandleData.handleData(countDataAfter,allTime,countSampling/countLength,initTime, HandleData.WINDOW_1024,HandleData.WINDOW_SIZE_20,HandleData.MULTIPLIER_3);
349 | countLength=0;
350 | countSampling=0;
351 | initTime=initTimeAfter;
352 | }
353 |
354 | if (size <= 0)
355 | continue;
356 | // if(size<0) break;//是否注释
357 | frameData = new byte[size];
358 | // System.out.println("SIZE:" + size + " 获取源数组开始位置:" + pix + " 新数组大小:" + frameData.length + " 长度: "
359 | // + frame.getBitSize() + " 总大小:" + frameByte.length);//SIZE:168 获取源数组开始位置:796001 新数组大小:168 长度: 168 总大小:796124
360 | //System.arraycopy(frameByte, pix, frameData, 0, frame.getBitSize());
361 | size = size < frameByte.length - pix ? size : frameByte.length - pix;
362 | // if(frame.getSampling()<0){
363 | // for(int f=0;f= frameByte.length)
376 | break;
377 | frame.setBitData(frameData);//给frame对象赋值数据
378 | this.frameList.add(frame);
379 |
380 | System.out.println();
381 | // if (pix>500) break;
382 | //}
383 | }
384 | System.out.println("frameByteSize:"+frameByte.length+" dataSize:"+data.length);
385 | System.out.println("frameListSize:" + frameList.size());
386 | }
387 |
388 | public int[] changeData(byte[] mdata){
389 | int[] dataResult=new int[mdata.length];
390 | for(int i=0;i getAllTime(){
396 | return allTime;
397 | }
398 |
399 | public int getSampling(){
400 | return sampling;
401 | }
402 |
403 | }
404 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/free/Mp3Handle/MyMp3FileReader.java:
--------------------------------------------------------------------------------
1 | package com.example.free.Mp3Handle;
2 |
3 | import java.io.BufferedInputStream;
4 | import java.io.File;
5 | import java.io.FileInputStream;
6 | import java.io.IOException;
7 | import java.util.ArrayList;
8 | import java.util.HashMap;
9 | import java.util.Map;
10 |
11 | public class MyMp3FileReader {
12 | private static Map style = new HashMap();
13 |
14 | ArrayList labels=new ArrayList<>();
15 |
16 | String filename;
17 |
18 | private FileInputStream is=null;
19 | private BufferedInputStream bis=null;
20 |
21 | private SongInfo songInfo;
22 | private DataInfo dataInfo;
23 |
24 | private byte[] data;
25 |
26 | public MyMp3FileReader(String _filename){
27 |
28 | String[] mlabels={"AENC", "APIC", "COMM", "COMR", "ENCR", "EQUA", "ETCO", "GEOB", "GRID", "IPLS", "LINK", "MCDI", "MLLT", "OWNE", "PRIV", "PCNT", "POPM", "POSS", "RBUF", "RVAD", "RVRB", "SYLT", "SYTC", "TALB", "TBPM", "TCOM", "TCON", "TCOP", "TDAT", "TDLY", "TENC", "TEXT", "TFLT", "TIME", "TIT1", "TIT2", "TIT3", "TKEY", "TLAN", "TLEN", "TMED", "TOAL", "TOFN", "TOLY", "TOPE", "TORY", "TOWN", "TPE1", "TPE2", "TPE3", "TPE4", "TPOS", "TPUB", "TRCK", "TRDA", "TRSN", "TRSO", "TSIZ", "TSRC", "TSSE", "TYER", "TXXX", "UFID", "USER", "USLT", "WCOM", "WCOP", "WOAF", "WOAR", "WOAS", "WORS", "WPAY", "WPUB", "WXXX"};
29 | for(String s:mlabels){
30 | labels.add(s);
31 | }
32 |
33 | this.filename=_filename;
34 | File file=new File(filename);
35 | try{
36 | is=new FileInputStream(file);
37 | //bis=new BufferedInputStream(is);
38 |
39 | //dataInfo
40 | byte[] bufFront=new byte[10];
41 | is.read(bufFront, 0, 10);
42 | this.dataInfo = new DataInfo(bufFront);//标签头 版本号 标签大小之类的
43 |
44 | //headLabel
45 | byte[] headLabel = new byte[this.dataInfo.getSize()];
46 | is.read(headLabel, 0, headLabel.length);//往下读标签长度的字节,得到标签内容,赋值给headLabel
47 | int headLabelLength=this.ID3ByHeadList(headLabel);//得到标签信息(标题 作者等)return Map(name,data)
48 |
49 | //data
50 | data = new byte[(int) (file.length() - 128 - 10 - headLabelLength)];//总长度-结尾128-标签头10-标签,,数据不太符合
51 | //System.out.println("----------------------data.length:"+data.length+" headLabelLength:"+headLabelLength+" headLabel:"+headLabel.length);
52 | System.arraycopy(headLabel, headLabelLength, data, 0, headLabel.length-headLabelLength);
53 | is.read(data, headLabel.length-headLabelLength, data.length-(headLabel.length-headLabelLength));
54 |
55 | //songInfo
56 | byte[] bufLast=new byte[128];
57 | is.read(bufLast, 0, 128);//获取结尾歌曲信息
58 | this.songInfo = new SongInfo(bufLast);
59 | //System.out.println(" ********************** song tag:"+(char)bufLast[0]+(char)bufLast[1]+(char)bufLast[2]);
60 |
61 |
62 | }catch(Exception e){
63 | e.printStackTrace();
64 | }
65 | }
66 |
67 | private int ID3ByHeadList(byte[] buf) {//得到标签帧内容 标题 作者等
68 | /*TSSE软硬件编码格式
69 | *APIC图片
70 | *COMM注解评论 comments
71 | *TALB专辑
72 | *TIT2歌名 内容描述
73 | *TPE1作者
74 | *TPE2乐队成员
75 | *0000*/
76 |
77 | /*
78 | * 标签帧: | 数据名 | 数据长度 | 标记 | [真实数据] | .....
79 | */
80 | Map map = new HashMap();
81 | int length=0;
82 | int pix = 0;
83 | byte[] head;// 4 标识帧,说明其内容 TIT2表示内容为这首歌的标题,TPE1作者 TALB专辑 TRCK因规格是 TYER年代
84 | byte[] size;// 4 帧内容大小(只包含内容的大小)
85 | byte[] flag;// 2 存放标志 (c只读 i压缩 j加密等)
86 | int dataLeng = 0;
87 | byte[] dataBuf;// n
88 |
89 | int dataLengEauals0=0;
90 |
91 | // System.out.println("buf.length:" + buf.length);//230
92 | for (; pix < buf.length; ) {//循环几组 标题组 作者组等
93 | head = new byte[4];
94 | size = new byte[4];
95 | flag = new byte[2];
96 | System.arraycopy(buf, pix, head, 0, 4);
97 | pix = pix + 4;
98 | System.arraycopy(buf, pix, size, 0, 4);
99 | pix = pix + 4;
100 | System.arraycopy(buf, pix, flag, 0, 2);
101 | pix = pix + 2;
102 |
103 |
104 |
105 | //System.out.print("\n 标识帧,说明其内容 TIT2表示内容为这首歌的标题,TPE1作者 TALB专辑 TRCK因规格是 TYER年代:");
106 | // for(int i=0;i0&&grantResults[0]==PackageManager.PERMISSION_GRANTED){
89 | initMediaPlayer();
90 | }else{
91 | Toast.makeText(this,"you denied the permission",Toast.LENGTH_SHORT).show();
92 | finish();//拒绝时回到上一页面
93 | }
94 | break;
95 | default:
96 | }
97 | }
98 |
99 | @Override
100 | public void onClick(View v) {
101 | switch(v.getId()){
102 |
103 | case R.id.musicView:
104 | Intent intent=new Intent(MusicActivity.this,MusicViewActivity.class);
105 | startActivity(intent);
106 | break;
107 |
108 | case R.id.play:
109 | if(!mediaPlayer.isPlaying())
110 | mediaPlayer.start();
111 | break;
112 | case R.id.pause:
113 | if(mediaPlayer.isPlaying())
114 | mediaPlayer.pause();
115 | break;
116 | case R.id.stop:
117 | if(mediaPlayer.isPlaying()) {
118 | mediaPlayer.reset();//停止播放
119 | initMediaPlayer();//停止之后要再准备一次 //prepare start; pause start; reset prepare start,
120 | }
121 | break;
122 | case R.id.result:
123 | Toast.makeText(getApplicationContext(),"click result activity",Toast.LENGTH_SHORT).show();
124 | Intent intent1=new Intent(MusicActivity.this,ResultActivity.class);
125 | getApplicationContext().startActivity(intent1);
126 | break;
127 | default:
128 | }
129 | }
130 |
131 | @Override
132 | protected void onDestroy() {
133 | super.onDestroy();
134 | if(mediaPlayer!=null){
135 | mediaPlayer.stop();//中间强制退出时,要关掉播放器
136 | mediaPlayer.release();//释放播放器所占资源
137 |
138 | }
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/free/MusicViewActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.free;
2 |
3 | import androidx.recyclerview.widget.LinearLayoutManager;
4 | import androidx.recyclerview.widget.RecyclerView;
5 |
6 | import android.database.Cursor;
7 | import android.os.Bundle;
8 | import android.provider.MediaStore;
9 |
10 | import com.example.free.Classes.BaseActivity;
11 | import com.example.free.Classes.Music;
12 | import com.example.free.Classes.MusicAdapter;
13 |
14 | import java.util.ArrayList;
15 | import java.util.Collections;
16 | import java.util.List;
17 |
18 | public class MusicViewActivity extends BaseActivity {
19 |
20 | List musicList=new ArrayList<>();
21 |
22 | @Override
23 | protected void onCreate(Bundle savedInstanceState) {
24 | super.onCreate(savedInstanceState);
25 | setContentView(R.layout.activity_music_view);
26 |
27 | setTitle("选择歌曲");
28 |
29 | initMusics();
30 |
31 | RecyclerView recyclerView=findViewById(R.id.recyclerView);
32 |
33 | LinearLayoutManager layoutManager=new LinearLayoutManager(this);//线性布局管理器,可自行设置布局
34 | layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
35 | recyclerView.setLayoutManager(layoutManager);
36 |
37 | MusicAdapter musicAdapter=new MusicAdapter(musicList);
38 | recyclerView.setAdapter(musicAdapter);
39 |
40 |
41 |
42 | }
43 | public void initMusics() {
44 | // if(ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
45 | // != PackageManager.PERMISSION_GRANTED){
46 | // //申请权限,名字与manifest里面的一致,1为请求码;需要重写onRequestPermissionsResult的得到申请权限的回调函数
47 | // ActivityCompat.requestPermissions(this,new String[]{
48 | // Manifest.permission.WRITE_EXTERNAL_STORAGE},1
49 | // );
50 | // //这里是需要先把文件读出来,再处理
51 | // }
52 | Cursor cursor = null;
53 | try {
54 | //这里是利用了数据库,不用从sd卡里过滤目录
55 | cursor = getApplicationContext().getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
56 | , null, null, null, MediaStore.Audio.AudioColumns.IS_MUSIC);//这是查外存的;
57 |
58 | if (cursor != null) {
59 | while (cursor.moveToNext()) {
60 | System.out.println(cursor);
61 | String name=cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DISPLAY_NAME));
62 | //String MediaStore.Audio.Media.ARTIST;String xx.DATA;Int xx.DURATION;Long xx.SIZE
63 | String path=cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA));
64 | long size=cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.SIZE));
65 | long time=cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DURATION));
66 | System.out.println("#############################"+name);
67 | System.out.println("#############################"+path);
68 | if(name!=null)
69 | if(name.contains(".wav")||name.contains(".mp3"))
70 | musicList.add(new Music(name,path,size,time));
71 | // if(name.contains("Lov")||name.contains("克罗")||name.contains("万神纪"))
72 | // System.out.println("name:"+name+" size:"+size+" time:"+time);
73 | }
74 | }
75 | else
76 | System.out.println("********************cursor is null");
77 | Collections.reverse(musicList);
78 |
79 | } catch (Exception e) {
80 | e.printStackTrace();
81 | } finally {
82 | if (cursor != null)
83 | cursor.close();
84 | }
85 | }
86 |
87 |
88 |
89 | /*
90 | public void initMusics(){
91 | // if(ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
92 | // != PackageManager.PERMISSION_GRANTED){
93 | // //申请权限,名字与manifest里面的一致,1为请求码;需要重写onRequestPermissionsResult的得到申请权限的回调函数
94 | // ActivityCompat.requestPermissions(this,new String[]{
95 | // Manifest.permission.WRITE_EXTERNAL_STORAGE},1
96 | // );
97 | // //这里是需要先把文件读出来,再处理
98 | // }
99 | //Cursor cursor=null;
100 | try{
101 | //cursor.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,null,null,null);
102 | //File file = new File(Environment.getExternalStorageDirectory(),"*.mp3");
103 |
104 | // List mFiles=new ArrayList<>();
105 | // File root = Environment.getExternalStorageDirectory().getAbsoluteFile();
106 | // Toast.makeText(getApplicationContext(),root.getAbsolutePath(), Toast.LENGTH_SHORT).show();
107 | // File files[] = root.listFiles();
108 | // if (files != null) {
109 | // for (File f : files) {
110 | // if (f.isDirectory()) {
111 | // // getAllFiles(f);
112 | // } else {
113 | // if (f.getAbsolutePath().contains(".wav")) {
114 | // mFiles.add(f);
115 | // }else if (f.getAbsolutePath().contains(".ogg")){
116 | // mFiles.add(f);
117 | // }else if (f.getAbsolutePath().contains(".mp3")){
118 | // mFiles.add(f);
119 | // }
120 | // }
121 | // }
122 | // }
123 | List mFiles=getMusicFiles();
124 | for(int i=0;i getMusicFiles(){
143 | List mFiles=new ArrayList<>();
144 | File root=new File("/mnt/sdcard");
145 | // File root = Environment.getExternalStorageDirectory().getAbsoluteFile();
146 | // Toast.makeText(getApplicationContext(),root.getAbsolutePath(), Toast.LENGTH_SHORT).show();//"/storage/emulated/0/:
147 | //getChildFiles(mFiles,root);
148 | //return mFiles;
149 | return getChildFiles(mFiles,root);
150 | }
151 | public List getChildFiles(List mFiles,File file){
152 | File files[] = file.listFiles();
153 | if (files != null) {
154 | for (File f : files) {
155 | if (f.isDirectory()) {
156 | //if(mFiles.size()<10)
157 | getChildFiles(mFiles,f);
158 | } else {
159 | // if (f.getAbsolutePath().contains(".wav")) {
160 | // mFiles.add(f);
161 | // }else if (f.getAbsolutePath().contains(".ogg")){
162 | // mFiles.add(f);
163 | // }else
164 | if (f.getAbsolutePath().contains(".mp3")){
165 | mFiles.add(f);
166 | }
167 | // mFiles.add(new File(mFiles.size()+""));
168 | }
169 | }
170 | }
171 | Toast.makeText(getApplicationContext(),mFiles.size()+"",Toast.LENGTH_SHORT).show();
172 | return mFiles;
173 | }
174 | */
175 |
176 |
177 | }
178 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/free/OriginChoiceActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.free;
2 |
3 | import androidx.appcompat.app.AppCompatActivity;
4 |
5 | import android.content.Intent;
6 | import android.os.Bundle;
7 | import android.view.View;
8 | import android.widget.Button;
9 | import android.widget.ProgressBar;
10 | import android.widget.RadioButton;
11 | import android.widget.RadioGroup;
12 | import android.widget.Toast;
13 |
14 | import com.example.free.Classes.BaseActivity;
15 |
16 | public class OriginChoiceActivity extends BaseActivity {
17 |
18 | private RadioGroup roadCounts,blockCounts,rateCounts;
19 | // private RadioButton two,four,less,more,slow,middle,fast;
20 |
21 | private int roads=2;//2 4
22 | private int blocks=1;//1 2
23 | private int rates=2;//1 2 3
24 |
25 | String musicPath;
26 | long musicSize;
27 | long musicTime;
28 |
29 | @Override
30 | protected void onCreate(Bundle savedInstanceState) {
31 | super.onCreate(savedInstanceState);
32 | setContentView(R.layout.activity_origin_choice);
33 |
34 | setTitle("选择模式");
35 |
36 | roadCounts=findViewById(R.id.roadCounts);
37 | blockCounts=findViewById(R.id.blockCounts);
38 | rateCounts=findViewById(R.id.rateCounts);
39 | // two=findViewById(R.id.two);
40 | // four=findViewById(R.id.four);
41 | // less=findViewById(R.id.less);
42 | // more=findViewById(R.id.more);
43 | // slow=findViewById(R.id.slow);
44 | // middle=findViewById(R.id.middle);
45 | // fast=findViewById(R.id.fast);
46 |
47 | Intent intentFrom=getIntent();
48 | musicPath=intentFrom.getStringExtra("musicPath");
49 | musicSize=intentFrom.getLongExtra("musicSize",0);
50 | musicTime=intentFrom.getLongExtra("musicTime",musicTime);
51 |
52 |
53 | RadioGroupListener radioGroupListener=new RadioGroupListener();
54 | roadCounts.setOnCheckedChangeListener(radioGroupListener);
55 | blockCounts.setOnCheckedChangeListener(radioGroupListener);
56 | rateCounts.setOnCheckedChangeListener(radioGroupListener);
57 |
58 |
59 | Button start=findViewById(R.id.start);
60 | start.setOnClickListener(new View.OnClickListener() {
61 | @Override
62 | public void onClick(View v) {
63 |
64 | // ProgressBar progressBar=findViewById(R.id.progressBar);
65 | // progressBar.setVisibility(View.VISIBLE);
66 |
67 | switch(roads){
68 | case 2:{
69 | Intent intent=new Intent(getApplicationContext(),GameActivity.class);
70 | intent.putExtra("className","OriginChoiceActivity");
71 | // Toast.makeText(getApplicationContext(),roads+"",Toast.LENGTH_SHORT).show();
72 | // System.out.println("******************"+ roads);
73 | intent.putExtra("blocks",blocks);
74 | intent.putExtra("rates",rates);
75 | intent.putExtra("musicPath",musicPath);
76 | intent.putExtra("musicSize", musicSize);
77 | intent.putExtra("musicTime",musicTime);
78 | startActivity(intent);
79 | break;
80 | }
81 | case 4:{
82 | Intent intent=new Intent(getApplicationContext(),FourGameActivity.class);
83 | intent.putExtra("className","OriginChoiceActivity");
84 | // Toast.makeText(getApplicationContext(),roads+"",Toast.LENGTH_SHORT).show();
85 | // System.out.println("******************"+ roads);
86 | intent.putExtra("blocks",blocks);
87 | intent.putExtra("rates",rates);
88 | intent.putExtra("musicPath",musicPath);
89 | intent.putExtra("musicSize", musicSize);
90 | intent.putExtra("musicTime",musicTime);
91 | startActivity(intent);
92 | break;
93 | }
94 | default:
95 | }
96 |
97 | }
98 | });
99 |
100 |
101 |
102 |
103 | Button advancedChoice=findViewById(R.id.advancedChoice);
104 | advancedChoice.setOnClickListener(new View.OnClickListener() {
105 | @Override
106 | public void onClick(View v) {
107 | Intent intent=new Intent(getApplicationContext(),ChoiceActivity.class);
108 | intent.putExtra("musicPath",musicPath);
109 | intent.putExtra("musicSize", musicSize);
110 | intent.putExtra("musicTime",musicTime);
111 | startActivity(intent);
112 | }
113 | });
114 |
115 | }
116 |
117 | class RadioGroupListener implements RadioGroup.OnCheckedChangeListener{
118 | @Override
119 | public void onCheckedChanged(RadioGroup group, int checkedId) {
120 | if(group==roadCounts){
121 | switch (checkedId){
122 | case R.id.two:
123 | roads=2;break;
124 | case R.id.four:
125 | roads=4;break;
126 | default:
127 | }
128 | }
129 | else{
130 | if(group==blockCounts){
131 | switch (checkedId){
132 | case R.id.less:
133 | blocks=1;break;
134 | case R.id.more:
135 | blocks=2;break;
136 | default:
137 | }
138 | }
139 | else{//rateCounts
140 | switch (checkedId){
141 | case R.id.slow:
142 | rates=1;break;
143 | case R.id.middle:
144 | rates=2;break;
145 | case R.id.fast:
146 | rates=3;break;
147 | default:
148 | }
149 | }
150 | }
151 | }
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/free/ResultActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.free;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.view.View;
6 | import android.widget.Button;
7 | import android.widget.TextView;
8 |
9 | import com.example.free.Classes.BaseActivity;
10 |
11 | public class ResultActivity extends BaseActivity {
12 |
13 | @Override
14 | protected void onCreate(Bundle savedInstanceState) {
15 | super.onCreate(savedInstanceState);
16 | setContentView(R.layout.activity_result);
17 |
18 | setTitle("得分");
19 |
20 | // Button forceOffline=findViewById(R.id.forceOffline);
21 | // forceOffline.setOnClickListener(new View.OnClickListener() {
22 | // @Override
23 | // public void onClick(View v) {
24 | // Intent intent=new Intent("force_offline");
25 | // sendBroadcast(intent);
26 | //
27 | // }
28 | // });
29 |
30 | Intent intent=getIntent();
31 |
32 | TextView wholeScore=findViewById(R.id.result_wholeScore);
33 | wholeScore.setText("WholeScore:"+intent.getIntExtra("wholeScore",0));
34 | TextView score=findViewById(R.id.result_score);
35 | score.setText("Score:"+intent.getIntExtra("resultScore",0));
36 | TextView bestTimes=findViewById(R.id.result_bestTimes);
37 | bestTimes.setText("Best:"+intent.getIntExtra("bestTimes",0));
38 | TextView goodTimes=findViewById(R.id.result_goodTimes);
39 | goodTimes.setText("Good:"+intent.getIntExtra("goodTimes",0));
40 | TextView missTimes=(findViewById(R.id.result_missTimes));
41 | missTimes.setText("Miss:"+intent.getIntExtra("missTimes",0));
42 |
43 |
44 |
45 | }
46 |
47 | @Override
48 | protected void onDestroy() {
49 | super.onDestroy();
50 | Intent intent=new Intent("force_offline");
51 | sendBroadcast(intent);
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/free/WavHandle/WaveFileReader.java:
--------------------------------------------------------------------------------
1 | package com.example.free.WavHandle;
2 |
3 | import java.io.*;
4 |
5 | public class WaveFileReader {
6 | private String filename = null;
7 | private int[][] data = null;
8 |
9 | private int len = 0;
10 |
11 | private String chunkdescriptor = null;
12 | static private int lenchunkdescriptor = 4;
13 |
14 | private long chunksize = 0;
15 | static private int lenchunksize = 4;
16 |
17 | private String waveflag = null;
18 | static private int lenwaveflag = 4;
19 |
20 |
21 | private String fmtubchunk = null;
22 | static private int lenfmtubchunk = 4;
23 |
24 | private long subchunk1size = 0;
25 | static private int lensubchunk1size = 4;
26 |
27 | private int audioformat = 0;
28 | static private int lenaudioformat = 2;
29 |
30 | private int numchannels = 0;
31 | static private int lennumchannels = 2;
32 |
33 | private long samplerate = 0;
34 | static private int lensamplerate = 2;
35 |
36 | private long byterate = 0;
37 | static private int lenbyterate = 4;
38 |
39 | private int blockalign = 0;
40 | static private int lenblockling = 2;
41 |
42 | private int bitspersample = 0;
43 | static private int lenbitspersample = 2;
44 |
45 | private String datasubchunk = null;
46 | static private int lendatasubchunk = 4;
47 |
48 | private long subchunk2size = 0;
49 | static private int lensubchunk2size = 4;
50 |
51 |
52 | private FileInputStream fis = null;
53 | private BufferedInputStream bis = null;
54 |
55 | private boolean issuccess = false;
56 |
57 | public WaveFileReader(String filename) {
58 |
59 | this.initReader(filename);
60 | }
61 |
62 | // 判断是否创建wav读取器成功
63 | public boolean isSuccess() {
64 | return issuccess;
65 | }
66 |
67 | // 获取每个采样的编码长度,8bit或者16bit
68 | public int getBitPerSample(){
69 | return this.bitspersample;
70 | }
71 |
72 | // 获取采样率
73 | public long getSampleRate(){
74 | return this.samplerate;
75 | }
76 |
77 | // 获取声道个数,1代表单声道 2代表立体声
78 | public int getNumChannels(){
79 | return this.numchannels;
80 | }
81 |
82 | // 获取数据长度,也就是一共采样多少个
83 | public int getDataLen(){
84 | return this.len;
85 | }
86 |
87 | // 获取数据
88 | // 数据是一个二维数组,[n][m]代表第n个声道的第m个采样值
89 | public int[][] getData(){
90 | return this.data;
91 | }
92 |
93 | private void initReader(String filename){
94 | this.filename = filename;
95 |
96 | try {
97 | fis = new FileInputStream(this.filename);//读取文件
98 | bis = new BufferedInputStream(fis);//转为二进制流
99 |
100 | //块描述符,前四个字节,判断是不是wave文件,wave数据块chunk由两个子数据块subchunk组成
101 | this.chunkdescriptor = readString(lenchunkdescriptor);//lenchunkdescriptor=4;
102 | //System.out.print(chunkdescriptor+" ");//"RIFF"
103 | if(!chunkdescriptor.endsWith("RIFF"))
104 | throw new IllegalArgumentException("RIFF miss, " + filename + " is not a wave file.");
105 |
106 | //readLong()都是四字节四字节读的,readInt()都是两字节两字节读的,,这与wave文件格式有关
107 | this.chunksize = readLong();//总长度
108 | //System.out.print(chunksize+" ");//8398
109 | this.waveflag = readString(lenwaveflag);//lenwaveflag=4;
110 | //System.out.print(waveflag+" ");//"WAVE"
111 | if(!waveflag.endsWith("WAVE"))
112 | throw new IllegalArgumentException("WAVE miss, " + filename + " is not a wave file.");
113 |
114 |
115 | this.fmtubchunk = readString(lenfmtubchunk);
116 | //System.out.print(fmtubchunk+" ");//"fmt "
117 | if(!fmtubchunk.endsWith("fmt "))
118 | throw new IllegalArgumentException("fmt miss, " + filename + " is not a wave file.");
119 |
120 | this.subchunk1size = readLong();//第一个子数据块说明数据的结构,子数据块长度为16字节
121 | //System.out.print(subchunk1size+" ");//16
122 |
123 | /**fmt-subchunk*/
124 | this.audioformat = readInt();//格式种类,值为1时为线性PCM编码
125 | //System.out.print(audioformat+" ");//1
126 | this.numchannels = readInt();//声道数,1为单声道,2为双声道
127 | //System.out.print(numchannels+" ");//1
128 | this.samplerate = readLong();//采样率,一秒钟采样次数
129 | //System.out.print(samplerate+" ");//16000
130 | this.byterate = readLong();//字节率,波形数据传输速率
131 | //System.out.print(byterate+" ");//32000
132 | this.blockalign = readInt();//data数据块长度(声道数*采样精度/8),这里为2,是16位单声道,数据块为 左声道低,左声道高
133 | //System.out.print(blockalign+" ");//2
134 | this.bitspersample = readInt();//采样精度,一次采样的位数,16bits,2bytes,PCM位宽
135 | //System.out.print(bitspersample+" ");//16
136 |
137 | /**data-subchunk*/
138 | this.datasubchunk = readString(lendatasubchunk);
139 | //System.out.print(datasubchunk+" ");//"data"
140 | if(!datasubchunk.endsWith("data"))
141 | throw new IllegalArgumentException("data miss, " + filename + " is not a wave file.");
142 | this.subchunk2size = readLong();
143 | //System.out.println(subchunk2size+" ");//8362字节
144 |
145 | this.len = (int)(this.subchunk2size/(this.bitspersample/8)/this.numchannels);//这里去掉了bitspersample,所以在采集的时候要按照8 16选择不同的读取长度。
146 |
147 | this.data = new int[this.numchannels][this.len];
148 | /*音频数据传输编码格式是 8位双声道时 左声道 右声道 左声道 右声道,16位双声道时 左声道低 左声道高 右声道低 右声道高 (左右声道交叉)
149 | 8位单声道 左声道 左声道 16位单声道 左声道低 左声道高 左声道低 左声道高 */
150 |
151 |
152 | for(int i=0; i>右移 11>>1=1
215 | * */
216 |
217 | private long readLong(){
218 | long res = 0;
219 | try {
220 | long[] l = new long[4];
221 | for(int i=0; i<4; ++i){
222 | l[i] = bis.read();
223 | //System.out.print("'"+l[i]);//206 32 0 0
224 | if(l[i]==-1){
225 | throw new IOException("no more data!!!");
226 | }
227 | }
228 | res = l[0] | (l[1]<<8) | (l[2]<<16) | (l[3]<<24);//8398 206+32*2^8
229 | } catch (IOException e) {
230 | e.printStackTrace();
231 | }
232 | return res;
233 | }
234 |
235 | private byte[] readBytes(int len){
236 | byte[] buf = new byte[len];
237 | try {
238 | if(bis.read(buf)!=len)
239 | throw new IOException("no more data!!!");
240 | } catch (IOException e) {
241 | e.printStackTrace();
242 | }
243 | return buf;
244 | }
245 | }
246 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/anim.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/_b2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lyrh-git/Free/4714064eb2124c02f3523ee6a0122e246b1a6680/app/src/main/res/drawable/_b2.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/_note.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lyrh-git/Free/4714064eb2124c02f3523ee6a0122e246b1a6680/app/src/main/res/drawable/_note.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/_r3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lyrh-git/Free/4714064eb2124c02f3523ee6a0122e246b1a6680/app/src/main/res/drawable/_r3.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/b1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lyrh-git/Free/4714064eb2124c02f3523ee6a0122e246b1a6680/app/src/main/res/drawable/b1.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/b_bottom.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lyrh-git/Free/4714064eb2124c02f3523ee6a0122e246b1a6680/app/src/main/res/drawable/b_bottom.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/background_auto.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/r2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lyrh-git/Free/4714064eb2124c02f3523ee6a0122e246b1a6680/app/src/main/res/drawable/r2.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/r4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lyrh-git/Free/4714064eb2124c02f3523ee6a0122e246b1a6680/app/src/main/res/drawable/r4.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/shape.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/layout-land/activity_four_game.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
29 |
30 |
41 |
42 |
43 |
44 |
51 |
52 |
53 |
59 |
68 |
69 |
70 |
76 |
85 |
86 |
92 |
101 |
102 |
108 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
139 |
140 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
24 |
25 |
37 |
38 |
60 |
61 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_choice.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
24 |
33 |
34 |
38 |
47 |
57 |
58 |
59 |
63 |
72 |
82 |
83 |
84 |
88 |
97 |
107 |
108 |
112 |
121 |
131 |
132 |
133 |
138 |
139 |
149 |
150 |
151 |
152 |
157 |
158 |
159 |
169 |
170 |
171 |
172 |
173 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_game.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
27 |
28 |
39 |
40 |
41 |
42 |
43 |
50 |
51 |
52 |
58 |
67 |
68 |
69 |
75 |
84 |
85 |
86 |
87 |
88 |
104 |
105 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
76 |
88 |
89 |
90 |
98 |
111 |
112 |
113 |
114 |
115 |
126 |
127 |
128 |
129 |
130 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_music.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
18 |
19 |
26 |
33 |
40 |
47 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_music_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_origin_choice.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
16 |
23 |
24 |
30 |
40 |
41 |
50 |
51 |
52 |
53 |
54 |
58 |
65 |
66 |
72 |
82 |
83 |
92 |
93 |
94 |
95 |
96 |
100 |
107 |
108 |
114 |
123 |
124 |
134 |
135 |
144 |
145 |
146 |
147 |
148 |
153 |
154 |
159 |
168 |
169 |
170 |
175 |
176 |
186 |
187 |
188 |
189 |
190 |
195 |
196 |
197 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_result.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
19 |
20 |
21 |
32 |
33 |
34 |
35 |
40 |
41 |
51 |
52 |
53 |
54 |
63 |
64 |
65 |
66 |
75 |
76 |
77 |
78 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/music_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
14 |
15 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/toast.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/toast_land.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lyrh-git/Free/4714064eb2124c02f3523ee6a0122e246b1a6680/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lyrh-git/Free/4714064eb2124c02f3523ee6a0122e246b1a6680/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lyrh-git/Free/4714064eb2124c02f3523ee6a0122e246b1a6680/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lyrh-git/Free/4714064eb2124c02f3523ee6a0122e246b1a6680/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lyrh-git/Free/4714064eb2124c02f3523ee6a0122e246b1a6680/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lyrh-git/Free/4714064eb2124c02f3523ee6a0122e246b1a6680/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lyrh-git/Free/4714064eb2124c02f3523ee6a0122e246b1a6680/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lyrh-git/Free/4714064eb2124c02f3523ee6a0122e246b1a6680/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lyrh-git/Free/4714064eb2124c02f3523ee6a0122e246b1a6680/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lyrh-git/Free/4714064eb2124c02f3523ee6a0122e246b1a6680/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #008577
4 | #00574B
5 | #D81B60
6 | #000000
7 | #ffffff
8 | #00bfff
9 | #1B8A22
10 | #333333
11 | #E0A86F
12 | #E6E8FA
13 | #D9D919
14 | #F8E097
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Free
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/test/java/com/example/free/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.example.free;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | google()
6 | jcenter()
7 |
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:3.5.0'
11 |
12 | // NOTE: Do not place your application dependencies here; they belong
13 | // in the individual module build.gradle files
14 | }
15 | }
16 |
17 | allprojects {
18 | repositories {
19 | google()
20 | jcenter()
21 |
22 | }
23 | }
24 |
25 | task clean(type: Delete) {
26 | delete rootProject.buildDir
27 | }
28 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app's APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Automatically convert third-party libraries to use AndroidX
19 | android.enableJetifier=true
20 |
21 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lyrh-git/Free/4714064eb2124c02f3523ee6a0122e246b1a6680/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Nov 22 19:02:56 CST 2019
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 | rootProject.name='Free'
3 |
--------------------------------------------------------------------------------