提示:转到安卓学习专栏,观看更多内容!
点我直达–>安卓学习专栏
内容关于本学期学习的安卓的基础知识。
MZH-学号19145120个人安卓学习大作业记录,可供参考学习。
期末大作业 音乐播放器源码 https://blog.csdn.net/u011027547/article/details/122376235
仓促整理,如有错误,欢迎指正。
我理解这题的意思是Andrdoid应用程序最重要的的是main文件夹
路径:项目名\app\src\main\下方的三个文件夹
Main文件夹中最重要的3个文件:
1.java(功能文件,实现业务逻辑功能)
2.res(资源文件,存放图片音乐、多语言版本字符串、drawable文件夹中可放入xml样式文件夹、layout布局文件夹)
3. AndroidManifest(清单文件,存放关于app主题、应用名称、权限管理、活动管理等内容)
外观文件中的tools:context=".MainActivity">
表示关联了包名路径查找后的MainActivity功能文件.MainActivity中的“.”表示包名路径
功能文件java文件中的R.layout.activity_main
表示关联R(res)文件夹中的layout文件中的activity的外观文件
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
捕获组件:
//爱好多选框
private CheckBox cb1 = null;
private CheckBox cb2 = null;
private CheckBox cb3 = null;
//爱好多选框
cb1 = (CheckBox) findViewById(R.id.cb1);
cb2 = (CheckBox) findViewById(R.id.cb2);
cb3 = (CheckBox) findViewById(R.id.cb3);
设置事件函数:
<CheckBox
android:id="@+id/cb1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:clickable="true"
android:onClick="CheckAll"
android:text="音乐"
android:textSize="15dp" />
编写事件函数:
//爱好多选
public void CheckAll(View v) {
String allString = "";
if (cb1.isChecked()) {
allString = allString + cb1.getText().toString() + "\n";
}
if (cb2.isChecked()) {
allString = allString + cb2.getText().toString() + "\n";
}
if (cb3.isChecked()) {
allString = allString + cb3.getText().toString() + "\n";
}
//if (allString.trim().length()>0) 一样的效果
if (!allString.equals("")) { //避免都不选择时吐司
Toast tt = Toast.makeText(this, "你选择了:\n" + allString, Toast.LENGTH_SHORT);
tt.setGravity(Gravity.CENTER, 0, 0);
ImageView img = new ImageView(this);
img.setImageResource(R.drawable.hoppy);
LinearLayout out = (LinearLayout) tt.getView();
out.setOrientation(LinearLayout.HORIZONTAL);
out.addView(img, 0);
tt.show();
} else {
Toast.makeText(this, "你什么爱好都没有选,怎么回事", Toast.LENGTH_SHORT).show();
}
}
捕获组件:
private RadioButton rbtn1 = null;
private RadioButton rbtn2 = null;
rbtn1 = (RadioButton) findViewById(R.id.rbtn1);
rbtn2 = (RadioButton) findViewById(R.id.rbtn2);
设置监听:
rbtn1.setOnClickListener(this);
rbtn2.setOnClickListener(this);
调用接口:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
实现接口方法:
public void onClick(View v) {
String allString = "";
int id = v.getId();
switch (id) {
case R.id.btn1: //如果id为btn1进行如下操作
//函数操作
break;
}
case R.id.btn1: //隐式启动
tt = new Intent("aa.bb.cc.dd");
startActivity(tt);
Toast.makeText(this, "隐式启动", Toast.LENGTH_LONG);
break;
case R.id.btn2://显式启动
Toast.makeText(this, "显式启动", Toast.LENGTH_LONG);
tt = new Intent(MainActivity.this, Main2Activity.class);
startActivity(tt);
break;
通过finshed()关闭页面
利用Handler刷新界面
实例化一个Handler对象,并重写handleMessage方法调用invalidate()实现界面刷新;而在线程中通过sendMessage发送界面更新消息。
// 在onCreate()中开启线程
new Thread(new GameThread()).start();
// 实例化一个handler
Handler myHandler = new Handler() {
//接收到消息后处理
public void handleMessage(Message msg) {
switch (msg.what) {
case Activity01.REFRESH:
mGameView.invalidate();//刷新界面
break;
}
super.handleMessage(msg);
}
};
class GameThread implements Runnable {
public void run() {
while (!Thread.currentThread().isInterrupted()) {
Message message = new Message();
message.what = Activity01.REFRESH;
//发送消息
Activity01.this.myHandler.sendMessage(message);
try {
Thread.sleep(100);
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
使用postInvalidate()刷新界面
使用postInvalidate则比较简单,不需要handler,直接在线程中调用postInvalidate即可。
class GameThread implements Runnable {
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(100);
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// 使用postInvalidate可以直接在线程中更新界面
mGameView.postInvalidate();
}
}
}
在子项中显示图片,样式文件中android:background 或者是java功能文件setBackground()方法
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="80dp"
android:gravity="center"
android:background="@drable/img">
linearLayout. setBackground(R.drawable. img);//设置左上角小图标
子项比较复杂,有多项显示内容:新建一个自定义的xml样式文件,类同上述方法调用xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="80dp"
android:gravity="center"
android:background="@drable/myitem">
linearLayout. setBackground(R.drawable. myitem);//设置左上角小图标
注意,运用文件时,不需要文件的后缀名,比如文件名可以是img但不能是img.jpg
下图是一个myitem.xml
1、与其它数据库不同,SQLite的数据类型很简单,只有
NULL(空类型)
INTEGER(整型)
REAL(浮点型)
TEXT(字符串型)
BLOB(二进制型)
2、SQLite为动态数据类型(弱引用),当向数据库中插入某个值时,会检查该值的类型,若类型与插入列不匹配,SQLite会尝试将该值转换成相应类型。
大多数 SQL 数据库引擎 (据我们所知,除 SQLite 之外的所有 SQL 数据库引擎)都使用严格的静态类型。使用静态类型,值的类型便由它的容器 – 存储值的特定的列 – 来决定。
SQLite 使用更通用的动态类型系统。在 SQLit 中,值的数据类型与值本身相关,而不是与它的容器。SQLite 的动态类型系统与其它数据库引擎的常用静态类型系统是向后兼容的,在这个意义上,工作在静态类型数据库上的 SQL 语句应该以同样的方式工作在 SQLite 中。然而,SQLite 中的动态类型允许它做传统的严格类型的数据库所不能做的事。
我的理解就是类似与python和C语言和java的区别,动态语言与静态语言的区别。
MyOpenHelper.java
public MyOpenHelper(@Nullable Context context, @Nullable SQLiteDatabase.CursorFactory factory) {
super(context, My_DATABASE, factory, My_VERSION);
}
//当数据库文件被创建时,调用该方法,并且只能被调用一次
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
String sql="create table shiyan3_users(" +
"id integer primary key autoincrement," +
"name varchar(50) not null," +
"sex varchar(50) not null," +
"age integer not null," +
"pwd varchar(24) not null," +
"phone varchar(20) not null)";
sqLiteDatabase.execSQL(sql);
}
Usersdao.java
调用MyOpenHelper,使用获取的SQLiteDatabase对象查询比对密码数据
//密码查询
public String queryPwd(String name) {
String pwd = null;
try {
String whereClause = "name=?";
String[] whereArgs = {name};
SQLiteDatabase db = helper.getWritableDatabase();
Cursor cursor = null;
cursor = db.query("shiyan3_users", null, whereClause, whereArgs, null, null, null);
if (cursor.moveToFirst()) {
for (int i = 0; i < cursor.getCount(); i++) {
pwd = cursor.getString(4);
cursor.moveToNext();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return pwd;
}
1、UI线程,负责与用户交互;
2、打开播放音乐时,一定启动了工作线程,该线程只负责音乐播放。
Android多线程的Handler—实现工作线程通知Main线程修改界面。Handler是一套 Android 消息传递机制。在多线程的应用场景中,将工作线程中需更新UI的操作信息传递到UI主线程,从而实现工作线程对UI的更新处理,最终实现异步消息的处理。
生成1个MediaPlayer类的对象
创建MediaPlaer对象有两种方式:
a、直接new出来
MediaPlayer mp = new MediaPlayer( );
b、使用create方式
MediaPlayer mp = MediaPlayer. create( this, R.raw.test );
R.raw.test:资源中的音乐文件,这时就不用调用setDataSource了
使用MediaPlayer类自动播放音乐:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
action=intent.getStringExtra("action");
index=intent.getIntExtra("index",0);
progress=intent.getIntExtra("progress",0);
Ok=intent.getBooleanExtra("ok",true);
switch (action){
case "play"://-------启动
int tt=0;
if (mp.isPlaying()==false){
mp.start();
work.ok=true;
tt=1;
}else {
mp.pause();
work.ok=false;
tt=-1;
}
Message mm=Message.obtain();
mm.what=200;
mm.arg1=tt;
MainActivity.hh.sendMessage(mm);
break;
case "click":
Goto();
break;
case "prev":
Goto();
break;
case "next":
Goto();
break;
case "change":
mp.seekTo(progress);
work.ok=Ok;
break;
}
return super.onStartCommand(intent, flags, startId);
}
9.1异步加载音乐文件:
mp.start();// 调用此方法,代表异步准备完成 开始播放
调用setDataSource()方法来设置音频文件的路径;
MediaPlayer的setDataSource一共四个方法:
A、setDataSource (String path)
B、setDataSource (FileDescriptor fd)
C、setDataSource (Context context, Uri uri)
D、setDataSource (FileDescriptor fd, long offset, long length)
9.2自动播放音乐mp.start();// 调用此方法,代表异步准备完成 开始播放
private void Goto(){
work.ok=false;
mp.stop();
mp.reset();
if (index>=MainActivity.list.size()){
index=0;
}
if (index<0){
index=MainActivity.list.size()-1;
}
try {
String ss=MainActivity.list.get(index).getUrl();
Uri uri=Uri.parse(ss);
mp.setDataSource(this,uri);
mp.setOnPreparedListener(this);
mp.prepareAsync();
mp.start();// 调用此方法,代表异步准备完成 开始播放
work.ok=true;
}catch (IOException e){
e.printStackTrace();
}
}
来自博主https://blog.csdn.net/Gods_magic/article/details/84558169
10.1绑定服务的方式,实现ServiceConnection接口
bindService() - unbindService()
10.1.1进行数据传递
Service中声明一个Binder类,类中声明用来传递数据的方法。比如向Activity返回Service实例/接受或返回数据。
Activity实现ServiceConnection接口,Activity绑定Service调用bindService()方法。此时onServiceConnected()方法就会被调用。此方法中利用获取的Binder实例,可以调用Service中各个用来传递数据的方法。
这就实现了Activity向Service传递数据,Service接收数据进行数据操作后,再返回给Activity。
10.1.2.Activity监听Service数据变化
Service自定义Callback接口,声明监听数据的抽象函数onDataChange(String data),参数data用来向外部暴露data数据,并设置callback实例的setter方法。再onCreat()方法中,Service利用接收来的data数据,进行耗时操作后(例如开启线程进行data的循环递增),用callback.onDataChange(data + “”)暴露data数据。
Activity在onServiceConnected()方法中,利用获取的Service实例调用setCallback()方法,同时实例化Callback接口,进行接口回调实现onDataChange()函数,此时就监听到了Service中data数据的状态,并利用Handler进行更新UI操作。
@Override
public void onCreate() {
super.onCreate();
try {
mp=new MediaPlayer();
String ss= MainActivity.list.get(index).getUrl();
Uri uri=Uri.parse(ss);
mp.setDataSource(this,uri);
mp.setOnPreparedListener(this);
mp.setOnCompletionListener(this);
mp.setOnErrorListener(this);
mp.prepareAsync();
work=new Work();
work.start();
}catch (IOException e){
e.printStackTrace();
}
}
//--------------------------------------------
private void Goto(){
work.ok=false;
mp.stop();
mp.reset();
if (index>=MainActivity.list.size()){
index=0;
}
if (index<0){
index=MainActivity.list.size()-1;
}
try {
String ss=MainActivity.list.get(index).getUrl();
Uri uri=Uri.parse(ss);
mp.setDataSource(this,uri);
mp.setOnPreparedListener(this);
mp.prepareAsync();
mp.start();
work.ok=true;
}catch (IOException e){
e.printStackTrace();
}
}
10.2利用广播方式
startService() - stopService()
Activity:动态注册广播 。将data存储到intent中,调用startService(intent)开启服务。
Service:重写onStartCommand()方法,利用intent.getXXExtra()获取Activity传来的数据。对数据进行操作后,将data存到intent中并发送广播。
Activity:接收广播,重写onReceive()函数,开启主线程并从intent中取出data数据,进行更新UI操作。
利用广播和intent实现了数据通信和监听服务数据状态。
MyService.java
public class MyService3 extends Service {
private boolean connecting = false;
public static final String COUNTER = "data";
public static final String ACTION_NAME = "com.example.myinterview.service3.COUNTER_ACTION";
private int data;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//从Activity获取data
data = intent.getIntExtra(COUNTER, 0);
final Intent mIntent = new Intent();
mIntent.setAction(ACTION_NAME);
connecting = true;
//开启一个线程,对数据进行处理
new Thread(new Runnable() {
@Override
public void run() {
try {
while (connecting) {
//耗时操作:数据处理并保存,向Activity发送广播
mIntent.putExtra(COUNTER, data);
sendBroadcast(mIntent);
data++;
Thread.sleep(300);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
connecting = false;
}
}
ServiceActivity3.java
public class ServiceActivity3 extends AppCompatActivity implements View.OnClickListener {
private int TransforData;
private TextView textView;
private Intent mIntent;
private MyReceiver myReceiver;
private boolean bind = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_service3);
TransforData = 0;
textView = (TextView) findViewById(R.id.textView);
Button startBtn = (Button) findViewById(R.id.mstart);
Button pauseBtn = (Button) findViewById(R.id.pause);
Button clearBt = (Button) findViewById(R.id.clear);
startBtn.setOnClickListener(this);
pauseBtn.setOnClickListener(this);
clearBt.setOnClickListener(this);
mIntent = new Intent(this, MyService3.class);
myReceiver = new MyReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(MyService3.ACTION_NAME);
//注册广播
registerReceiver(myReceiver, intentFilter);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.mstart:
if (!bind) {
bind = true;
//向Service传递data
mIntent.putExtra(MyService3.COUNTER, TransforData);
startService(mIntent);
Toast.makeText(this, "Start!", Toast.LENGTH_SHORT).show();
}
break;
case R.id.pause:
//停止服务
stopService(mIntent);
bind = false;
break;
case R.id.clear:
if (!bind) {
TransforData = 0;
textView.setText("0");
Toast.makeText(this, "Pause!", Toast.LENGTH_SHORT).show();
}
break;
default:
break;
}
}
class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, final Intent intent) {
runOnUiThread(new Runnable() {
@Override
public void run() {
//获取从Service中传来的data
TransforData = intent.getIntExtra(MyService3.COUNTER, 0);
//更新UI
textView.setText(String.valueOf(TransforData));
}
});
}
}
@Override
protected void onDestroy() {
stopService(mIntent);
unregisterReceiver(myReceiver);
super.onDestroy();
}
}
大家喜欢的话,给个,点个关注!继续跟大家分享敲代码过程中遇到的问题!