目录
开发环境
功能清单
部分源码
login.java
MainActivity.java
MyDatabase.java
build.gradle
源码下载
学习安卓开发时做的一个小demo,知识点包括:intent、UI、界面切换、API调用、播放器调用、内部存储、list控件等。
具体可看视频:
简单的安卓网络音乐视频播放器app
截图:
开发环境
开发工具:Android Studio
音视频接口:网易云API,项目地址:网易云音乐 API service
功能清单
账号:注册、登录、删除、记住密码
音视频:搜索、播放/暂停音乐、播放/暂停视频、上一曲/下一曲
部分源码
当时初学,写的比较粗糙,仅供参考
login.java
package com.sxf.myapp;import androidx.appcompat.app.AppCompatActivity;import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteCursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast;public class login extends AppCompatActivity implements View.OnClickListener {private static final String TAG = "LOGIN";private Button button_signin;private Button button_signup;private Button button_delete;private EditText editText_pwd;private EditText editText_usr;private CheckBox checkBox_rmpwd;private SQLiteDatabase db;private Cursor cursor;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_login);button_signin = findViewById(R.id.button_signin);button_signup = findViewById(R.id.button_signup);button_delete = findViewById(R.id.button_delete);editText_pwd = findViewById(R.id.editText_pwd);editText_usr = findViewById(R.id.editText_usr);checkBox_rmpwd = findViewById(R.id.checkBox_rmpwd);button_signin.setOnClickListener(this);button_signup.setOnClickListener(this);button_delete.setOnClickListener(this);SharedPreferences sharedPreferences = getSharedPreferences("loginFile", MODE_PRIVATE);Boolean rm = sharedPreferences.getBoolean("rm", false);if (rm){checkBox_rmpwd.setChecked(true);String temp = "";temp = sharedPreferences.getString("usr", "");editText_usr.setText(temp);temp = sharedPreferences.getString("pwd", "");editText_pwd.setText(temp);}Toast.makeText(this,"读取记录完成", Toast.LENGTH_SHORT).show();db = SQLiteDatabase.openOrCreateDatabase(this.getFilesDir().toString()+"login.db", null);try {db.rawQuery("select * from users;", null);}catch (Exception e){e.printStackTrace();db.execSQL("create table users(id INTEGER PRIMARY KEY AUTOINCREMENT,usr VARCHAR(20) DEFAULT NULL,pwd VARCHAR(20) DEFAULT NULL);");}}@Overrideprotected void onDestroy() {super.onDestroy();if (!checkBox_rmpwd.isSelected()){SharedPreferences sharedPreferences = getSharedPreferences("loginFile", MODE_PRIVATE);SharedPreferences.Editor editor = sharedPreferences.edit();
// editor.putString("usr","");
// editor.putString("pwd","");editor.putBoolean("rm",checkBox_rmpwd.isChecked());editor.apply();}Toast.makeText(this,"欢迎下次光临", Toast.LENGTH_SHORT).show();}@Overridepublic void onClick(View v) {String usr = editText_usr.getText().toString();String pwd = editText_pwd.getText().toString();if (TextUtils.isEmpty(usr) || TextUtils.isEmpty(pwd)){Toast.makeText(this,"请先输入用户名和密码", Toast.LENGTH_SHORT).show();return;}switch (v.getId()){case R.id.button_signin: //登录try {if (!db.isOpen()){db = SQLiteDatabase.openOrCreateDatabase(this.getFilesDir().toString()+"login.db", null);}cursor = db.rawQuery("select * from users where usr=(?) AND pwd=(?)", new String[]{usr, pwd},null);Log.i(TAG, "登录: "+cursor.getCount());if (cursor.getCount()==0){Toast.makeText(this,"用户名或密码错误", Toast.LENGTH_SHORT).show();}else {cursor.moveToFirst();String res = cursor.getString(1);Toast.makeText(this,"欢迎你,"+res, Toast.LENGTH_SHORT).show();db.close();SharedPreferences sharedPreferences = getSharedPreferences("loginFile", MODE_PRIVATE);SharedPreferences.Editor editor = sharedPreferences.edit();if (checkBox_rmpwd.isChecked()){editor.putString("usr",usr);editor.putString("pwd",pwd);}else {editor.putString("usr","");editor.putString("pwd","");}editor.putBoolean("rm",checkBox_rmpwd.isChecked());editor.apply();Intent intent = new Intent(login.this, MainActivity.class);startActivity(intent);}}catch (Exception e){e.printStackTrace();}break;case R.id.button_signup: // 注册try {cursor = db.rawQuery("select * from users where usr=(?)", new String[]{usr},null);Log.i(TAG, "注册: "+cursor.getCount());if (cursor.getCount()==0){db.execSQL("INSERT INTO users VALUES(null, ?,?)", new String[]{usr,pwd});cursor = db.rawQuery("select * from users where usr=(?)", new String[]{usr},null);if (cursor.getCount()==0){Toast.makeText(this,"注册失败", Toast.LENGTH_SHORT).show();}else {Toast.makeText(this,"注册成功", Toast.LENGTH_SHORT).show();}}else {Toast.makeText(this,"该用户已存在", Toast.LENGTH_SHORT).show();}}catch (Exception e){e.printStackTrace();}break;case R.id.button_delete:try {cursor = db.rawQuery("select * from users where usr=(?)", new String[]{usr},null);Log.i(TAG, "删户: "+cursor.getCount());if (cursor.getCount()>0){db.execSQL("DELETE FROM users WHERE usr=(?)", new String[]{usr});cursor = db.rawQuery("select * from users where usr=(?)", new String[]{usr},null);if (cursor.getCount()==0){Toast.makeText(this,"删除成功", Toast.LENGTH_SHORT).show();}else {Toast.makeText(this,"删除失败", Toast.LENGTH_SHORT).show();}}else {Toast.makeText(this,"该用户不存在", Toast.LENGTH_SHORT).show();}}catch (Exception e){e.printStackTrace();}break;default:break;}}
}
MainActivity.java
package com.sxf.myapp;import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;import android.annotation.SuppressLint;
import android.content.Intent;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;public class MainActivity extends AppCompatActivity implements View.OnClickListener {private static final String TAG = "DEBUG";private Button button_search;private Button button_musicplay;private Button button_musicpause;private Button button_lastPage;private Button button_nextPage;private EditText editText_search;private TextView textView_searchResult;private Spinner spinner;private ListView listView_resultShow;private ArrayAdapter<String> adapterListView;private String rootURL = "http://121.36.68.53:3000/";private int offset = 0;private String[] idArrays;private int idArraysIndex = 0;private int checkMusicFlag = 0;private String selectedMusicUrl = null;private String selectedItem = null;private MediaPlayer mediaPlayer;private TextView textView_lrc;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);button_search = findViewById(R.id.button_search);editText_search = findViewById(R.id.editText_search);textView_searchResult = findViewById(R.id.textView_searchResult);spinner = findViewById(R.id.spinner_class);listView_resultShow = findViewById(R.id.listview_resultshow);button_search.setOnClickListener(this);idArrays = new String[10];mediaPlayer = new MediaPlayer();textView_lrc = findViewById(R.id.textView_lrc);button_musicplay = findViewById(R.id.button_musicplay);button_musicpause = findViewById(R.id.button_musicpause);button_musicplay.setOnClickListener(this);button_musicpause.setOnClickListener(this);button_lastPage = findViewById(R.id.button_lastPage);button_nextPage = findViewById(R.id.button_nextPage);button_lastPage.setOnClickListener(this);button_nextPage.setOnClickListener(this);adapterListView = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1);listView_resultShow.setAdapter(adapterListView);listView_resultShow.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {button_nextPage.setVisibility(View.GONE);button_lastPage.setVisibility(View.GONE);String code = idArrays[position].split(",")[0];String vid = idArrays[position].split(",")[1];String name = idArrays[position].split(",")[2];Log.i(TAG, "onItemClick "+vid);getMusicUrl(vid, code);selectedItem = name;Log.i(TAG, "selectedItem: "+selectedItem);}});}@SuppressLint("HandlerLeak")Handler handler = new Handler(){@Overridepublic void handleMessage(@NonNull Message msg) {if (msg.what>0){String res = (String) msg.obj;if (msg.what==200){Log.i(TAG, "checkMusic: "+res);JSONObject obj = JSONObject.parseObject(res);if (obj!=null){if(obj.getBooleanValue("success")){checkMusicFlag = 1;}else {checkMusicFlag = -1;}}return;}if (msg.what==201){ // get music urlif (res!=null){System.out.println(res);JSONObject obj = JSONObject.parseObject(res);JSONArray data = obj.getJSONArray("data");if (data!=null){selectedMusicUrl = data.getJSONObject(0).getString("url");Log.i(TAG, "handleMessage201: "+selectedMusicUrl);findViewById(R.id.include_textview).setVisibility(View.VISIBLE);listView_resultShow.setVisibility(View.GONE);textView_searchResult.setVisibility(View.GONE);if (selectedMusicUrl!=null){textView_lrc.setText("");textView_lrc.append(selectedItem);textView_lrc.append("\n\n");textView_lrc.append(selectedMusicUrl);
// playMusic(selectedMusicUrl);}else {textView_lrc.setText("没找到你要的东西");}}return;}}else if (msg.what==202){ // get mv urlif (res!=null){System.out.println(res);JSONObject obj = JSONObject.parseObject(res);JSONObject data = obj.getJSONObject("data");if (data!=null){selectedMusicUrl = data.getString("url");Log.i(TAG, "handleMessage202: "+selectedMusicUrl);findViewById(R.id.include_textview).setVisibility(View.VISIBLE);listView_resultShow.setVisibility(View.GONE);textView_searchResult.setVisibility(View.GONE);if (selectedMusicUrl!=null){textView_lrc.setText("");textView_lrc.append(selectedItem);textView_lrc.append("\n\n");textView_lrc.append(selectedMusicUrl);}else {textView_lrc.setText("没找到你要的东西");}}return;}}JSONObject json = JSON.parseObject(res);JSONObject result = json.getJSONObject("result");Integer count = 0;JSONArray songs = null;switch (msg.what){case 1:count = result.getInteger("songCount");if (count>0){songs = result.getJSONArray("songs");for (Object o :songs) {JSONObject item = (JSONObject) o;Integer id = item.getInteger("id");String name = item.getString("name");JSONObject artists = item.getJSONArray("artists").getJSONObject(0);String artistName = artists.getString("name");idArrays[idArraysIndex++] = 1+","+id+","+name;Log.i(TAG, id+" - "+name+" - "+artistName);findViewById(R.id.include_textview).setVisibility(View.GONE);textView_searchResult.setVisibility(View.GONE);listView_resultShow.setVisibility(View.VISIBLE);adapterListView.add(name+" - "+artistName);}}break;case 10:count = result.getInteger("albumCount");if (count>0){songs = result.getJSONArray("albums");for (Object o :songs) {JSONObject item = (JSONObject) o;Integer id = item.getInteger("id");String name = item.getString("name");JSONObject artists = item.getJSONArray("artists").getJSONObject(0);String artistName = artists.getString("name");idArrays[idArraysIndex++] = 10+","+id+","+name;Log.i(TAG, id+" - "+name+" - "+artistName);findViewById(R.id.include_textview).setVisibility(View.GONE);textView_searchResult.setVisibility(View.GONE);listView_resultShow.setVisibility(View.VISIBLE);adapterListView.add(name+" - "+artistName);}}break;case 100:count = result.getInteger("artistCount");if (count>0){songs = result.getJSONArray("artists");for (Object o :songs) {JSONObject item = (JSONObject) o;Integer id = item.getInteger("id");String name = item.getString("name");Log.i(TAG, id+" - "+name+" - "+name);idArrays[idArraysIndex++] = 100+","+id+","+name;findViewById(R.id.include_textview).setVisibility(View.GONE);textView_searchResult.setVisibility(View.GONE);listView_resultShow.setVisibility(View.VISIBLE);adapterListView.add(name);}}break;case 1000:count = result.getInteger("playlistCount");if (count>0){songs = result.getJSONArray("playlists");for (Object o :songs) {JSONObject item = (JSONObject) o;Integer id = item.getInteger("id");String name = item.getString("name");idArrays[idArraysIndex++] = 1000+","+id+","+name;Log.i(TAG, id+" - "+name);findViewById(R.id.include_textview).setVisibility(View.GONE);textView_searchResult.setVisibility(View.GONE);listView_resultShow.setVisibility(View.VISIBLE);adapterListView.add(name);}}break;case 1002:count = result.getInteger("userprofileCount");if (count>0){songs = result.getJSONArray("userprofiles");for (Object o :songs) {JSONObject item = (JSONObject) o;Integer id = item.getInteger("userId");String name = item.getString("nickname");idArrays[idArraysIndex++] = 1002+","+id+","+name;Log.i(TAG, id+" - "+name);findViewById(R.id.include_textview).setVisibility(View.GONE);textView_searchResult.setVisibility(View.GONE);listView_resultShow.setVisibility(View.VISIBLE);adapterListView.add(name);}}break;case 1004:count = result.getInteger("mvCount");if (count>0){songs = result.getJSONArray("mvs");for (Object o :songs) {JSONObject item = (JSONObject) o;Integer id = item.getInteger("id");String name = item.getString("name");JSONObject artists = item.getJSONArray("artists").getJSONObject(0);String artistName = artists.getString("name");idArrays[idArraysIndex++] = 1004+","+id+","+name;Log.i(TAG, id+" - "+name+" - "+artistName);findViewById(R.id.include_textview).setVisibility(View.GONE);textView_searchResult.setVisibility(View.GONE);listView_resultShow.setVisibility(View.VISIBLE);adapterListView.add(name+" - "+artistName);}}break;case 1006:count = result.getInteger("songCount");if (count>0){songs = result.getJSONArray("songs");for (Object o :songs) {JSONObject item = (JSONObject) o;Integer id = item.getInteger("id");String name = item.getString("name");JSONObject artists = item.getJSONArray("artists").getJSONObject(0);String artistName = artists.getString("name")+","+name;idArrays[idArraysIndex++] = 1006+","+id;Log.i(TAG, id+" - "+name+" - "+artistName);findViewById(R.id.include_textview).setVisibility(View.GONE);textView_searchResult.setVisibility(View.GONE);listView_resultShow.setVisibility(View.VISIBLE);adapterListView.add(name+" - "+artistName);}}break;case 1009:count = result.getInteger("djRadiosCount");if (count>0){songs = result.getJSONArray("djRadios");for (Object o :songs) {JSONObject item = (JSONObject) o;Integer id = item.getInteger("id");String name = item.getString("name");idArrays[idArraysIndex++] = 1009+","+id+","+name;Log.i(TAG, id+" - "+name);findViewById(R.id.include_textview).setVisibility(View.GONE);textView_searchResult.setVisibility(View.GONE);listView_resultShow.setVisibility(View.VISIBLE);adapterListView.add(name);}}break;case 1014:count = result.getInteger("videoCount");if (count>0){songs = result.getJSONArray("videos");for (Object o :songs) {JSONObject item = (JSONObject) o;String id = item.getString("vid");String name = item.getString("title");idArrays[idArraysIndex++] = 1014+","+id+","+name;Log.i(TAG, id+" - "+name);findViewById(R.id.include_textview).setVisibility(View.GONE);textView_searchResult.setVisibility(View.GONE);listView_resultShow.setVisibility(View.VISIBLE);adapterListView.add(name);}}break;default:break;}if (count==0){findViewById(R.id.include_textview).setVisibility(View.GONE);listView_resultShow.setVisibility(View.GONE);textView_searchResult.setText("没找到你要的东西");textView_searchResult.setVisibility(View.VISIBLE);return;}}}};public void playMusic(String url){if (url != null){try {mediaPlayer.setDataSource(url);mediaPlayer.prepare();} catch (Exception e) {e.printStackTrace();}}if (!mediaPlayer.isPlaying()){mediaPlayer.start();}}public void stopMusic(){if (mediaPlayer.isPlaying()) {mediaPlayer.stop();}mediaPlayer.reset();}public void pauseMusic(){if (mediaPlayer.isPlaying()) {mediaPlayer.pause();}}public void destroyMusic(){if (mediaPlayer != null) {if (mediaPlayer.isPlaying()) {mediaPlayer.stop();}mediaPlayer.release();}}public Boolean isPlayMusic(){return mediaPlayer.isPlaying();}static void getWebInfoThread(final URL url, final Handler handler, final Integer what){new Thread(new Runnable() {@Overridepublic void run() {try {HttpURLConnection httpURLConnection = (HttpURLConnection)url.openConnection();InputStream inputStream = httpURLConnection.getInputStream();InputStreamReader reader = new InputStreamReader(inputStream, "UTF-8");BufferedReader bufferedReader = new BufferedReader(reader);StringBuilder buffer = new StringBuilder();String temp = null;while ((temp = bufferedReader.readLine())!=null){buffer.append(temp);}bufferedReader.close();reader.close();inputStream.close();handler.sendMessage(handler.obtainMessage(what, buffer.toString()));}catch (Exception e){e.printStackTrace();}}}).start();}public Boolean checkMusic(String id){try {URL url = new URL(rootURL+"check/music?id="+id);getWebInfoThread(url, handler, 200);while (checkMusicFlag==0){Thread.sleep(1000);};if (checkMusicFlag==1) return true;if (checkMusicFlag==-1) return false;}catch (Exception e){e.printStackTrace();}return false;}public void getMusicUrl(String id, String code){try {if (code.equals("1004")){URL url = new URL(rootURL+"mv/url?id="+id);getWebInfoThread(url, handler, 202);}else {URL url = new URL(rootURL+"song/url?id="+id);getWebInfoThread(url, handler, 201);}}catch (Exception e){e.printStackTrace();}}public void doSearch(int off){if (!TextUtils.isEmpty(editText_search.getText())){adapterListView.clear();stopMusic();idArraysIndex = 0;URL url = null;try {String msg = editText_search.getText().toString();String spinnerItem = spinner.getSelectedItem().toString().split(" ")[0];url = new URL(rootURL+"search?keywords="+URLEncoder.encode(msg,"utf-8")+"&limit=10&type="+spinnerItem+"&offset="+off);final URL finalUrl = url;Log.i(TAG, "URL: "+finalUrl);getWebInfoThread(finalUrl, handler, Integer.parseInt(spinnerItem));} catch (Exception e) {e.printStackTrace();}}}@Overridepublic void onClick(View v) {switch (v.getId()){case R.id.button_search:offset = 0;button_nextPage.setVisibility(View.VISIBLE);button_lastPage.setVisibility(View.VISIBLE);adapterListView.clear();doSearch(0);break;case R.id.button_musicplay:if(!isPlayMusic()) {if (selectedMusicUrl.contains(".mp4")){Intent intent = new Intent(Intent.ACTION_VIEW);Uri uri = Uri.parse(selectedMusicUrl);intent.setDataAndType(uri, "video/3gp");startActivity(intent);}else {playMusic(selectedMusicUrl);}}break;case R.id.button_musicpause:if(isPlayMusic()){pauseMusic();}break;case R.id.button_lastPage:if (offset<10) offset=10;offset -= 10;doSearch(offset);break;case R.id.button_nextPage:offset += 10;doSearch(offset);break;default:break;}}
}
MyDatabase.java
package com.sxf.myapp;import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;import androidx.annotation.Nullable;public class MyDatabase extends SQLiteOpenHelper {public MyDatabase(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {super(context, name, factory, version);}@Overridepublic void onCreate(SQLiteDatabase db) {}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
}
build.gradle
apply plugin: 'com.android.application'android {compileSdkVersion 29buildToolsVersion "29.0.3"defaultConfig {applicationId "com.sxf.myapp"minSdkVersion 21targetSdkVersion 29versionCode 1versionName "1.0"testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}}dependencies {implementation fileTree(dir: 'libs', include: ['*.jar'])implementation 'androidx.appcompat:appcompat:1.1.0'implementation 'androidx.constraintlayout:constraintlayout:1.1.3'implementation 'com.google.android.material:material:1.0.0'implementation 'androidx.annotation:annotation:1.1.0'implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'testImplementation 'junit:junit:4.12'androidTestImplementation 'androidx.test.ext:junit:1.1.1'androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'implementation 'com.android.support:localbroadcastmanager:29.0.0'implementation files('libs/fastjson-1.2.66.jar')
}