You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

649 lines
27 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package com.example.musicwork.freeModel;
//自由模式的主活动
//此模式只支持4/4拍只能编写八分音符
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Environment;
//import android.support.annotation.StringDef;
//import android.support.v4.app.ActivityCompat;
import android.provider.ContactsContract;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import android.widget.Toast;
//import android.media.midi.;
import com.example.musicwork.Data;
import com.example.musicwork.R;
import com.example.musicwork.chuangguan.PianoMusic;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
//import android.support.v7.app.AppCompatActivity;
public class FreemdActivity extends AppCompatActivity {
//进行动态权限申请
private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
"android.permission.READ_EXTERNAL_STORAGE",
"android.permission.WRITE_EXTERNAL_STORAGE" };
MusicScoreLayout musicScoreLayout;//自定义乐谱布局
boolean highFlag = false;//记录高音按钮是否选中
boolean lowFlag = false;//记录低音按钮是否选中
//boolean inctimeFlag = false;//记录增时线按钮是否选中
boolean dectimeFlag = false;//记录减时线按钮是否选中
//int position = 0;//记录每个layout在musicLayout里的位置
List<MusicNote> noteList = new ArrayList<MusicNote>();//存储简谱中的每个音符
int index = 0;//记录每个音符在音符列表里的索引
ArrayList<View> noteLayoutList = new ArrayList<View>();//存储音符layout和增时线
PianoMusic util;
String musicName;//音乐名
final Data data = (Data)getApplication();
String username;//用户名
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_freemd);
final Data data = (Data)getApplication();
username = data.getUsername();
util = new PianoMusic(this);//音乐播放器
musicScoreInit();//初始化乐谱每个组件大小
musicInfoInit();//初始化标题和拍号作者
btnInit();//初始化按钮并设置监听
}
//接受Intent中的数据初始化简谱名和节拍并设置作者
public void musicInfoInit(){
Bundle bundle = this.getIntent().getExtras();
String flag = bundle.getString("flag");
if (flag.equals("init")){
//传入音乐名和节号
//Log.e("map",""+flag);
musicName = bundle.getString("musicName");
String musicBeat = bundle.getString("musicBeat");
//设置bundle中传入的数据名字节拍
TextView musicNameView = (TextView)findViewById(R.id.title);
TextView musicBeatView = (TextView)findViewById(R.id.score_kind);
musicNameView.setText(musicName);
musicBeatView.setText(musicBeat);
//设置作者
TextView usernameView = (TextView)findViewById(R.id.author);
usernameView.setText(username);
}else if (flag.equals("open")){
//传入音乐文件信息
int length = bundle.getInt("length");
for (int i=0;i<length;i++){
String[] noteArray = bundle.getStringArray("note"+i);
int note = Integer.parseInt(noteArray[0]);
float beat = Float.parseFloat(noteArray[1]);
MusicNote musicNote = new MusicNote(note,beat);
noteList.add(musicNote);
}
//Log.e("map",""+i);
//画乐谱
drawScore();
}
}
//根据接收的noteList画乐谱
public void drawScore(){
for (int i=0;i<noteList.size();i++){
Log.e("map","open"+i);
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
MusicNote musicNote = noteList.get(i);
int note = musicNote.getNote();
float beat = musicNote.getBeat();
//自动设置分割线(根据拍号?
int count = musicScoreLayout.getChildCount();//得到子控件数量
if (count%5==4){//拍号为4/4拍
pauseLine();
}
//设置音符
TextView noteView = new TextView(this);
int text;
if(note>7&&note<15){
text = note-7;
}else if (note>14){
text = note-14;
}else {
text = note;
}
noteView.setText(""+text);
layout.addView(noteView);
if (note>14){//高音
//加高音点
ImageView highDot = new ImageView(this);
highDot.setImageResource(R.drawable.dot);
highDot.setLayoutParams(new LinearLayout.LayoutParams(20,20));
layout.addView(highDot,0);
}else if (note<8){//低音
ImageView lowDot = new ImageView(this);
lowDot.setImageResource(R.drawable.dot);
lowDot.setLayoutParams(new LinearLayout.LayoutParams(20,20));
layout.addView(lowDot,layout.getChildCount());
}
if (beat<1){//加减时线
//Log.e("map","减时线");
TextView decLine = new TextView(this);
decLine.setWidth(LinearLayout.LayoutParams.MATCH_PARENT);
decLine.setHeight(3);
decLine.setBackgroundColor(Color.BLACK);
if(note<8){//减时线放在低音点的上面
layout.addView(decLine,layout.getChildCount()-1);
}else{//高音点
layout.addView(decLine,layout.getChildCount());
}
musicScoreLayout.addView(layout);
}else if (beat>1){//加增时线
int num = (int)beat;
if (beat-num != 0){
//加减时线
TextView decLine = new TextView(this);
decLine.setWidth(LinearLayout.LayoutParams.MATCH_PARENT);
decLine.setHeight(3);
decLine.setBackgroundColor(Color.BLACK);
if(note<8){//减时线放在低音点的上面
layout.addView(decLine,layout.getChildCount()-1);
}else{//高音点
layout.addView(decLine,layout.getChildCount());
}
}
musicScoreLayout.addView(layout);
//加增时线
for (int j=1;j<num;j++){
TextView inctimeNote = new TextView(this);
inctimeNote.setWidth(10);
inctimeNote.setHeight(5);
inctimeNote.setBackgroundColor(Color.BLACK);
musicScoreLayout.addView(inctimeNote);
}
}else {
musicScoreLayout.addView(layout);
}
}
}
//乐谱布局初始化
public void musicScoreInit(){
musicScoreLayout = (MusicScoreLayout)findViewById(R.id.music_score);
//设置子控件宽高
musicScoreLayout.setHeight(200);
musicScoreLayout.setWidth(100);
}
//按下音符按钮在乐谱上添加对应音符(检查合法性?
public void onClick(View v){
Button btn = (Button)v;//音符按钮
MusicNote note = new MusicNote(Integer.parseInt(btn.getText().toString())+7,1);//此处音符是正常音符段1 拍?
noteList.add(note);//添加音符对象到列表
//自动设置分割线(根据拍号?
int count = musicScoreLayout.getChildCount();//得到子控件数量
if (count%5==4){//拍号为4/4拍
pauseLine();
}
final LinearLayout layout = new LinearLayout(v.getContext());
//MusicScoreLayout layout = new MusicScoreLayout(v.getContext());
layout.setOrientation(LinearLayout.VERTICAL);
//layout.setLayoutParams(new LinearLayout.LayoutParams(100,200));
layout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT));
//layout.setId(0);
if (noteLayoutList.size() != 0){
int position = noteLayoutList.get(noteLayoutList.size()-1).getId();
layout.setId(position+1);//列表索引,代表布局位置
}else {
layout.setId(0);
}
final TextView noteView = new TextView(this);
noteView.setText(btn.getText().toString());
noteView.setTextColor(Color.BLACK);
//设置id
noteView.setId(index);
index += 1;
//留出位置,对齐音符
final LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,50);
param.setMargins(0,20,0,23);
noteView.setLayoutParams(param);
layout.addView(noteView);
musicScoreLayout.addView(layout);
noteLayoutList.add(layout);//把布局放入List中存储位置
//音符view的点击事件
noteView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//升号
if (highFlag){
MusicNote note = noteList.get(v.getId());//得到当前音符
if (note.getNote()<8){ //音符已经为降号
Toast.makeText(getApplicationContext(),"不允许同一个音符上存在升号和降号",Toast.LENGTH_SHORT).show();
}else if(note.getNote()+7<22){
note.setNote(note.getNote()+7);//更改音符为升号
ImageView highDot = new ImageView(v.getContext());
highDot.setImageResource(R.drawable.dot);
highDot.setLayoutParams(new LinearLayout.LayoutParams(20,20));
//上外边距被填满
param.setMargins(0,0,0,23);
noteView.setLayoutParams(param);
layout.addView(highDot,0);
}else {
Toast.makeText(getApplicationContext(),"不允许音符继续升号",Toast.LENGTH_SHORT).show();
}
}
//降号
if(lowFlag){
MusicNote note = noteList.get(v.getId());
if (note.getNote()>14){//音符已经为升号
Toast.makeText(getApplicationContext(),"不允许同一个音符上存在升号和降号",Toast.LENGTH_SHORT).show();
}else if (note.getNote()-7>0){
note.setNote(note.getNote()-7);//更改音符为降号
ImageView lowDot = new ImageView(v.getContext());
lowDot.setImageResource(R.drawable.dot);
lowDot.setLayoutParams(new LinearLayout.LayoutParams(20,20));
//下外边距被填满
param.setMargins(0,20,0,3);
noteView.setLayoutParams(param);
layout.addView(lowDot,layout.getChildCount());
}else{
Toast.makeText(getApplicationContext(),"不允许音符继续降号",Toast.LENGTH_SHORT).show();
}
}
//减时线
if(dectimeFlag){
MusicNote note = noteList.get(v.getId());
note.setBeat(note.getBeat()-(float)1/2);//更改节拍
if (note.isDectimeFlag()){
Toast.makeText(v.getContext(),"不允许重复添加减时线",Toast.LENGTH_SHORT).show();
}else {
TextView decLine = new TextView(v.getContext());
decLine.setBackgroundColor(Color.BLACK);
LinearLayout.LayoutParams decparam = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 3);
//对齐
if (note.getNote() < 8) {//减时线放在低音点的上面
param.setMargins(0, 20, 0, 0);
decLine.setLayoutParams(decparam);
layout.addView(decLine, layout.getChildCount() - 1);
} else if (note.getNote() > 14) {//高音点
param.setMargins(0, 0, 0, 0);
decparam.setMargins(0, 0, 0, 20);
decLine.setLayoutParams(decparam);
layout.addView(decLine, layout.getChildCount());
} else {
param.setMargins(0, 20, 0, 0);
decparam.setMargins(0, 0, 0, 20);
decLine.setLayoutParams(decparam);
layout.addView(decLine, layout.getChildCount());
}
noteView.setLayoutParams(param);
note.setDectimeFlag(true);//表示添加了减时线
//只能先在前一个音符上加线,再在后一个音符上加?
//判断前后音符是否添加了减时线
//有则进行布局合并
int pos = layout.getId();//布局在musicLayoutList中的索引
int dex = v.getId();//音符在音符列表中的索引
int forward = dex-1;
int later = dex+1;
if (pos-1>=0){//第一个音符不用看前面音符
View forview = noteLayoutList.get(pos-1);//得到此布局的前一个view
if(!(forview instanceof TextView)){//前一个音符不是增时线
if (noteList.get(forward).isDectimeFlag()){//前一个音符加了减时线
LinearLayout anotherLayout = (LinearLayout)forview;//前一个布局
LinearLayout curLayout = (LinearLayout)noteLayoutList.get(pos);//本布局
if (anotherLayout.getChildAt(0) instanceof LinearLayout){
//Toast.makeText(v.getContext(),"只能有八分音符",Toast.LENGTH_SHORT).show();
Log.e("freemd_dectime","只能有八分音符");
}else {
musicScoreLayout.removeAllViews();//把所有音符全部移除
LinearLayout newLayout = new LinearLayout(v.getContext());
//anotherLayout
newLayout.addView(anotherLayout);
newLayout.addView(curLayout);
noteLayoutList.remove(pos);
noteLayoutList.remove(pos-1);
noteLayoutList.add(pos-1,newLayout);
//重新画乐谱
for (int i=0;i<noteLayoutList.size();i++){
//画音符
View view = noteLayoutList.get(i);
view.setId(i);//重新设置位置
musicScoreLayout.addView(view);
//画分割线
if (musicScoreLayout.getChildCount()%5==4){
pauseLine();
}
}
}
}
}
}
}
}
}
});
}
//生成分割线
public void pauseLine(){
//生成分割线
TextView tv = new TextView(this);
tv.setWidth(3);
tv.setHeight(50);
tv.setBackgroundColor(Color.BLACK);
musicScoreLayout.addView(tv);
}
public void verifyStoragePermissions() {
try {
//检测是否有写的权限
int permission = ActivityCompat.checkSelfPermission(FreemdActivity.this,
"android.permission.WRITE_EXTERNAL_STORAGE");
if (permission != PackageManager.PERMISSION_GRANTED) {
// 没有写的权限,去申请写的权限,会弹出对话框
ActivityCompat.requestPermissions(FreemdActivity.this, PERMISSIONS_STORAGE,REQUEST_EXTERNAL_STORAGE);
}
} catch (Exception e) {
e.printStackTrace();
}
}
//按钮的初始化及监听
public void btnInit(){
Button delete = (Button)findViewById(R.id.Del);
final Button highNote = (Button)findViewById(R.id.high_note);
final Button lowNote = (Button)findViewById(R.id.low_note);
final Button inctime = (Button)findViewById(R.id.inc_time);
final Button dectime = (Button)findViewById(R.id.dec_time);
Button playMusic = (Button)findViewById(R.id.play_music);
Button saveMusic = (Button)findViewById(R.id.save_music);
//删除按钮的监听(有选择的删除?
//删除后播放有问题?
delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
/* if(noteList.get(noteList.size()-1).getBeat()<1){//删除分割线和增时线时不会对列表做操作
noteList.remove(noteList.size()-1);//删除列表尾部的音符对象
}
if (musicScoreLayout.getChildCount()%5 != 0){//删除分割线时不会对列表做操作
noteLayoutList.remove(noteLayoutList.size()-1);//删除列表尾部的布局对象
}*/
if (musicScoreLayout.getChildCount()%5 != 0){//删除分割线时不会对列表做操作
View nllView = noteLayoutList.get(noteLayoutList.size()-1);
if (nllView instanceof LinearLayout){//不是增时线
if(((LinearLayout) nllView).getChildAt(0) instanceof LinearLayout){//假如是合并后的布局,需要删除两个音符
noteList.remove(noteList.size()-1);//删除列表尾部的音符对象
noteList.remove(noteList.size()-1);
index -= 2;
}else {
noteList.remove(noteList.size()-1);//删除列表尾部的音符对象
index -= 1;
}
}
noteLayoutList.remove(noteLayoutList.size()-1);//删除列表尾部的布局对象
}
int count = musicScoreLayout.getChildCount();
View delView = musicScoreLayout.getChildAt(count-1);
musicScoreLayout.removeView(delView);
}
});
//增时线按钮监听
inctime.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (noteList.size()==0){
Toast.makeText(view.getContext(),"不应在音符前添加增时线",Toast.LENGTH_SHORT).show();
}else {
MusicNote note = noteList.get(noteList.size()-1);
note.setBeat(note.getBeat()+1);//增加一个节拍
TextView inctimeNote = new TextView(view.getContext());
inctimeNote.setWidth(10);
inctimeNote.setHeight(5);
inctimeNote.setBackgroundColor(Color.BLACK);
//增时线id
if (noteLayoutList.size() != 0){
int position = noteLayoutList.get(noteLayoutList.size()-1).getId();
inctimeNote.setId(position+1);
}else {
inctimeNote.setId(0);
}
musicScoreLayout.addView(inctimeNote);
noteLayoutList.add(inctimeNote);
//自动生成分割线
int count = musicScoreLayout.getChildCount();//得到子控件数量
if (count%5==4){
pauseLine();
}
}
}
});
//给音符加高音/低音点按钮监听
highNote.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
highFlag = !highFlag;
lowFlag = false;
dectimeFlag = false;
if (highFlag){
v.setBackgroundColor(Color.parseColor("#ad9d69"));
}else {
v.setBackgroundColor(Color.parseColor("#cdb97a"));
}
lowNote.setBackgroundColor(Color.parseColor("#cdb97a"));
dectime.setBackgroundColor(Color.parseColor("#cdb97a"));
}
});
lowNote.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
lowFlag = !lowFlag;
highFlag = false;
dectimeFlag = false;
if (lowFlag){
v.setBackgroundColor(Color.parseColor("#ad9d69"));
}else {
v.setBackgroundColor(Color.parseColor("#cdb97a"));
}
highNote.setBackgroundColor(Color.parseColor("#cdb97a"));
dectime.setBackgroundColor(Color.parseColor("#cdb97a"));
}
});
//给音符加减时线按钮监听
dectime.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dectimeFlag = !dectimeFlag;
lowFlag = false;
highFlag = false;
if (dectimeFlag){
v.setBackgroundColor(Color.parseColor("#ad9d69"));
}else {
v.setBackgroundColor(Color.parseColor("#cdb97a"));
}
lowNote.setBackgroundColor(Color.parseColor("#cdb97a"));
highNote.setBackgroundColor(Color.parseColor("#cdb97a"));
}
});
//保存按钮监听
saveMusic.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//连接数据库存入list
//OutputStreamWriter out = null;
verifyStoragePermissions();
try {
File file = new File(Environment.getExternalStorageDirectory().getPath(),"/Music/"+musicName+".txt");
if (!file.exists())//如果不存在该文件
{
file.createNewFile();
}
RandomAccessFile fos = new RandomAccessFile(file.getPath(), "rwd");
for (int i = 0;i<noteList.size();i++){
MusicNote note = noteList.get(i);
fos.write((note.getNote()+" "+note.getBeat()).getBytes());
//换行符
String newLine = System.getProperty("line.separator");
fos.write(newLine.getBytes());
}
fos.close();
String filepath=file.getPath();
String filename=musicName+".txt";
if( FileServiceUpload.uploadForm(filepath,filename)){
Toast.makeText(getApplicationContext(),"保存成功",Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(getApplicationContext(),"保存失败",Toast.LENGTH_SHORT).show();
}
//Log.e("map",""+file.getPath());
}catch (Exception e){
e.printStackTrace();
}
}
});
//播放按钮监听
playMusic.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//在新的线程上播放音乐
playMusicRunnable runnable = new playMusicRunnable(v.getContext());
Thread thread = new Thread(runnable);
//启动线程
thread.start();
}
});
}
//播放音乐的线程
class playMusicRunnable implements Runnable {
Context context;
public playMusicRunnable(Context context) {
this.context = context;
}
@Override
public void run() {
try {
for (int i = 0;i<noteList.size();i++){
int note = noteList.get(i).getNote()-1;
if (note == 0){
Thread.sleep(2000);
}else {
util.soundPlay(note);
int beat = (int) (noteList.get(i).getBeat()*500);
Thread.sleep(beat);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}