android钢琴源码
㈠ 基于Android音乐播放器源代码(正常播放、有列表)
package my.android.players;
import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.TextView;
public class mainActivity extends Activity {
private List<String> myMusicList=new ArrayList<String>();
//当前播放歌曲的索引
private int currentListItem=0;
//音乐的路径
private static final String MUSIC_PATH="/sdcard/mp3";
//播放对象
private MediaPlayer myMediaPlayer;
private TextView m_TextView;
//播放按钮
private ImageButton m_start;
private ImageButton m_stop;
private ImageButton m_next;
private ImageButton m_last;
/*设定bIsPaused一开始为false */
private boolean bIsRun = false;
private boolean isplay;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main2);
myMediaPlayer=new MediaPlayer();
musicList();
m_TextView=(TextView)findViewById(R.id.mtextview);
m_start=(ImageButton)findViewById(R.id.imgbtn_start);
m_stop=(ImageButton)findViewById(R.id.imgbtn_stop);
m_next=(ImageButton)findViewById(R.id.imgbtn_next);
m_last=(ImageButton)findViewById(R.id.imgbtn_last);
listener();
Intent intent = this.getIntent();
Bundle bundle = intent.getExtras();
currentListItem = bundle.getInt("currentListItem");
isplay=bundle.getBoolean("isplay");
if(isplay==true)
{
bIsRun=false;
playMusic(MUSIC_PATH+"/"+myMusicList.get(currentListItem));
}
}
//监听事件
void listener(){
//开始
m_start.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
try
{
if(myMediaPlayer.isPlaying()==true)
{
myMediaPlayer.pause();
m_start.setImageResource(R.drawable.pause);
}
else
{
playMusic(MUSIC_PATH+"/"+myMusicList.get(currentListItem));
}
}
catch (IllegalStateException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
//下一首
m_next.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
nextMusic();
}
});
//上一首
m_last.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
lastMusic();
}
});
//停止
m_stop.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
stopMusic();
}
});
myMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
nextMusic();
}
});
}
//播放音乐
void playMusic(String path){
try {
if(bIsRun==false)
{
myMediaPlayer.reset();
myMediaPlayer.setDataSource(path);
myMediaPlayer.prepare();
myMediaPlayer.start();
/*
* 取出歌曲名的.mp3后缀
* */
String str=(myMusicList.get(currentListItem)).toString();
System.out.println(str);
String str1[]=str.split("\\.");
System.out.println(str1[0]);
m_TextView.setText(str1[0]);
}
else
{
myMediaPlayer.start();
}
m_start.setImageResource(R.drawable.start);
bIsRun=true;
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
//下一首
void nextMusic(){
if(++currentListItem>=myMusicList.size()){
currentListItem=0;
}
bIsRun=false;
playMusic(MUSIC_PATH+"/"+myMusicList.get(currentListItem));
}
//上一首
void lastMusic(){
if(--currentListItem<0)
currentListItem=myMusicList.size()-1;
bIsRun=false;
playMusic(MUSIC_PATH+"/"+myMusicList.get(currentListItem));
}
//停止
void stopMusic() {
if (myMediaPlayer.isPlaying()) {
m_start.setImageResource(R.drawable.pause);
myMediaPlayer.stop();// 停止
bIsRun=false;
}
else
playMusic(MUSIC_PATH+"/"+myMusicList.get(currentListItem));
}
//当用户返回时结束音乐并释放音乐对象
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
if(keyCode==KeyEvent.KEYCODE_BACK){
new AlertDialog.Builder(mainActivity.this).setTitle("message")
.setIcon(android.R.drawable.dialog_frame)
.setMessage("你确定要离开吗?")
.setPositiveButton("确定",new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
myMediaPlayer.stop();
myMediaPlayer.release();
finish();
}
}).setNegativeButton("取消",new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
}).show();
}
return super.onKeyDown(keyCode, event);
}
/**
* 文件过滤器
*
* @author
*
*/
class MusicFilter implements FilenameFilter {
@Override
public boolean accept(File dir, String filename) {
return (filename.endsWith(".mp3"));
}
}
//绑定音乐
void musicList(){
try{
File home=new File(MUSIC_PATH);
if(!home.exists())
home.mkdirs();
if(home.listFiles(new MusicFilter()).length>=0){
for(File file:home.listFiles(new MusicFilter())){
myMusicList.add(file.getName().toString());
}
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
}
package my.android.players;
import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class Activity01 extends Activity {
//播放列表
private List<String> myMusicList=new ArrayList<String>();
//当前播放歌曲的索引
private int currentListItem;
//音乐的路径
private static final String MUSIC_PATH="/sdcard/mp3";
//播放列表
private ListView m_ListView;
private boolean isplay=true;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
m_ListView=(ListView)findViewById(R.id.lv_music);
musicList();
//当选择列表项时播放音乐
m_ListView.setOnItemClickListener(new ListView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
currentListItem = arg2;
Intent intent = new Intent();
Bundle mBundle=new Bundle();
mBundle.putInt("currentListItem", currentListItem);
mBundle.putBoolean("isplay", isplay);
intent.putExtras(mBundle);
intent.setClass(Activity01.this,mainActivity.class);
startActivity(intent);
finish();
}
});
}
/**
* 文件过滤器
*
* @author
*
*/
class MusicFilter implements FilenameFilter {
@Override
public boolean accept(File dir, String filename) {
return (filename.endsWith(".mp3"));
}
}
//绑定音乐
void musicList(){
try{
File home=new File(MUSIC_PATH);
if(!home.exists())
home.mkdirs();
if(home.listFiles(new MusicFilter()).length>=0){
for(File file:home.listFiles(new MusicFilter())){
myMusicList.add(file.getName().toString());
}
ArrayAdapter<String> musicList=new ArrayAdapter<String>
(Activity01.this,android.R.layout.simple_list_item_1, myMusicList);
m_ListView.setAdapter(musicList);
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
}
㈡ android 添加背景音乐源码
一张你从伍迹手未填写过的巨额支票,
枯黄萎缩州旦的败叶,
不要去做,孩子
浪来时,你指着海洋彼岸
也会让有些人感到烦扰。
他腔嫌来的这中,哈哈
㈢ Android ScrollView 源码浅析
可以看到ScrollView继承自FrameLayout
构造函数中只对1个属性:fillViewport进行了提取,这个属性的作用是,如果被设置成true,ScrollView的子View将充满视图
ScrollView的onMeasure()函数,先调用了父类的super.onMeasure(),随后如果mFillViewport属性为false,实际上函数就结束,也就是说在mFillViewport为false的情况下,ScrollView在测量截断是没有额外工作的;如果mFillViewport为true,就会调用一次child的measure()方法来重新测量大小以达到充满视图的效果
ScrollView的onLayout()过程也是先调用了父类的onLayout(),随后会判断是否需要滑动到子View的位置;最后一行scrollTo(mScrollX, mScrollY)将滑动到对应的位置。中间的isLaidOut()是View里面掘或的方法,用于判断该View是否已经被添加到window上。
在draw()阶段涉及到的变量主要是mEdgeGlowTop和mEdgeGlowBottom,这两个变量判物伍的类型是EdgeEffect,用于控制边缘的阴影效果,ScrollView的draw()阶段主要工作是绘制了上下阴影
作为一个ViewGroup的子类,ScrollView与事件相关的有dispatchTouchEvent()/onInterceptTouchEvent()/onTouchEvent()这3个处理函数,其中ScrollView没有重写dispatchTouchEvent(),因此主要来关注下onInterceptTouchEvent()和onTouchEvent()这两个函数做了什么
由官方注释可以看出,onInterceptTouchEvent()只是决定是否拦截事件,而并不处理触摸逻辑。
首先会初始化VelocityTracker,这个类的作用是追踪触摸事件的加速度;最后会调用其addMovement()函数,中间部分是对各个动作的具体处理,下面看下各个动作都会怎样处理:
在ACTION_MOVE事件中需要关注的是,会调用View的overScrollBy()方法来真正处理触摸事件,overScrollBy()方法实现如下:
主要的流程就是根据传入的各个滑动参数,以及View本身与滑动相关的属性,计算出newScrollX/newScrollY等参数,然后调用onOverScrolled()方法来进行实际的滑动处理
onOverScrolled()方法在View中是空实现,因此具体的实现在ScrollView中:
有两条分支,mScroller.isFinished()为false证明上次的滑动还没有结束,这时需要计算出新的滑动位置进行滑动;如果此时不在滑动,则调用View的scrollTo()方法滑动到蚂橡对应位置;最后一行awakenScrollBars()作用是让ScrollBar显示出来
当手指抬起时,ScrollView的操作很简单,先判断是否处于滑动状态,如果不是就什么都不用干;如果是的话,需要让滑动继续惯性向前滑一段,这里借助了VelocityTracker和Scroller来实现。
㈣ 如何打开android 源代码
可以用配置了Android环境的eclipse,也可以直接用Android studio,都可以直接导入项目源码
㈤ 怎样查看 Android APP源代码
将apk文件拷贝至sdcard上。
命令顺序如下:
进入Android sdk文件夹/tools目录下
输入adb shell
输入su
输入cd data
输入cd app
这时就可以看到你安装的所有的apk文件。输入cp 空格 对应的apk 空格 /sdcard/
这样就将apk文件拷贝出来了。
将apk文件后缀直接变成rar格式,可以看到熟悉的目录结构了,
其中xml文件打开后都是二进制的,无法查看。
这时就用到了一个android4me的AXMLPrinter2工具。(请自行网络搜索)
输入以下命令,将xml文件解析出来
java -jar AXMLPrinter2.jar showtimes_list.xml
此命令是在命令行中查看此showtimes_list.xml
将showtimes_list.xml生成xml文件,则输入以下命令:
java -jar AXMLPrinter2.jar showtimes_list.xml > h.xml
目前进行到这一步,只能看到xml文件的内容,其工程中的java源文件还是看不到,看目录结构下有一个classes.dex文件,我们需要将dex文件变为jar文件。
这里用到了另一个工具dex2jar。(自行搜索下载)
在Windows下解压之后的目录如下图所示:
在命令行中,进入到此目录下:
在Windows下,输入以下命令:
dex2jar.bat c:classes.dex
运行完之后,在C盘会多一个classes.dex.dex2jar.jar文件,此文件就是我们需要的jar文件。
利用jd-gui,将jar文件反向工程为java代码。(请自行搜索下载)
它分为Windows、Linux、和max三个版本,这里我下载的是Windows版本的。
解压之后,双击运行exe文件,选择classes.dex.dex2jar.jar文件,相应的jar文件中的Java文件就被反向工程显示出来了!
㈥ 如何获取android源代码
当前的Android代码托管在两个方:https://github.com/android 和https://android.googlesource.com之前在 android.git.kernel.org上也有托管,不过现在重定向到了https://android.googlesource.com好在都支持git访问。
google提供的repo工具实际上是一个内部操作git工具来简化操作Android源码的Python脚本。经过尝试,直接使用git工具在ubuntu下可以实现cloneAndroid源码。下面介绍一下方法:
1.获取当前的在github上托管的Androidgitrepositories:
github页面为:https://github.com/android/following。不过这个页面不支持通过wget"https://github.com/android/following"或者curl"https://github.com/android/following"的方式访问,错误信息如下:
这个时候需能做的只能是"tryagain"了。
需要说明的是"不要试图同时并发执行多个gitclone命令",这样会导致大量出现上面贴图中的错误,另外,整个clone过程中耗时最多的gitrepository如下:
kernel_common.gitkernel_msm.gitplatform_frameworks_base.gitplatform_prebuilt.git其中platform_prebuilt.git是google提供的预编译好的二进制文件,包含:各种库文件,jar包,可执行程序等等,如果只是阅读Android源代码,这个gitrepository可以不用clone.
㈦ 怎样查看 Android APP 源代码
用压缩软件打开apk文件,解压出根目录中的classes.dex文件
使用cmd ,dex2jar.bat classes.dex命令将classes.dex转换为jar
再用jd-gui打开该jar就可以查看源码了,如果apk安全性好的话,有些代码是看不到的
㈧ 求android源码下载地址,就像学学源码的原理
Google刚刚公布,稳定版的Android源代码已经公布,任何人都可以免费下载。Google希望通过公布源代码,电信运营商和手机制造商,乃至一般开发者们进一步深刻了解和利用Android系统,从而有益于该平台下的的发展。
看来T-Mobile G1不一定打得过iPhone,那么Android呢?
现在源代码公布在http://source.android.com/,SDK网站是http://code.google.com/android/
㈨ Android socket源码解析(三)socket的connect源码解析
上一篇文章着重的聊了socket服务端的bind,listen,accpet的逻辑。本文来着重聊聊connect都做了什么?
如果遇到什么问题,可以来本文 https://www.jianshu.com/p/da6089fdcfe1 下讨论
当服务端一切都准备好了。客户端就会尝试的通过 connect 系统调用,尝试的和服务端建立远程连接。
首先校验当前socket中是否有正确的目标地址。然后获取IP地址和端口调用 connectToAddress 。
在这个方法中,能看到有一个 NetHooks 跟踪socket的调用,也能看到 BlockGuard 跟踪了socket的connect调用。因此可以hook这两个地方跟踪socket,不过很少用就是了。
核心方法是 socketConnect 方法,这个方法就是调用 IoBridge.connect 方法。同理也会调用到jni中。
能看到也是调用了 connect 系统调用。
文件:/ net / ipv4 / af_inet.c
在这个方法中做的事情如下:
注意 sk_prot 所指向的方法是, tcp_prot 中 connect 所指向的方法,也就是指 tcp_v4_connect .
文件:/ net / ipv4 / tcp_ipv4.c
本质上核心任务有三件:
想要能够理解下文内容,先要明白什么是路由表。
路由表分为两大类:
每个路由器都有一个路由表(RIB)和转发表 (fib表),路由表用于决策路由,转发表决策转发分组。下文会接触到这两种表。
这两个表有什么区别呢?
网上虽然给了如下的定义:
但实际上在Linux 3.8.1中并没有明确的区分。整个路由相关的逻辑都是使用了fib转发表承担的。
先来看看几个和FIB转发表相关的核心结构体:
熟悉Linux命令朋友一定就能认出这里面大部分的字段都可以通过route命令查找到。
命令执行结果如下:
在这route命令结果的字段实际上都对应上了结构体中的字段含义:
知道路由表的的内容后。再来FIB转发表的内容。实际上从下面的源码其实可以得知,路由表的获取,实际上是先从fib转发表的路由字典树获取到后在同感加工获得路由表对象。
转发表的内容就更加简单
还记得在之前总结的ip地址的结构吗?
需要进行一次tcp的通信,意味着需要把ip报文准备好。因此需要决定源ip地址和目标IP地址。目标ip地址在之前通过netd查询到了,此时需要得到本地发送的源ip地址。
然而在实际情况下,往往是面对如下这么情况:公网一个对外的ip地址,而内网会被映射成多个不同内网的ip地址。而这个过程就是通过DDNS动态的在内存中进行更新。
因此 ip_route_connect 实际上就是选择一个缓存好的,通过DDNS设置好的内网ip地址并找到作为结果返回,将会在之后发送包的时候填入这些存在结果信息。而查询内网ip地址的过程,可以成为RTNetLink。
在Linux中有一个常用的命令 ifconfig 也可以实现类似增加一个内网ip地址的功能:
比如说为网卡eth0增加一个IPV6的地址。而这个过程实际上就是调用了devinet内核模块设定好的添加新ip地址方式,并在回调中把该ip地址刷新到内存中。
注意 devinet 和 RTNetLink 严格来说不是一个存在同一个模块。虽然都是使用 rtnl_register 注册方法到rtnl模块中:
文件:/ net / ipv4 / devinet.c
文件:/ net / ipv4 / route.c
实际上整个route模块,是跟着ipv4 内核模块一起初始化好的。能看到其中就根据不同的rtnl操作符号注册了对应不同的方法。
整个DDNS的工作流程大体如下:
当然,在tcp三次握手执行之前,需要得到当前的源地址,那么就需要通过rtnl进行查询内存中分配的ip。
文件:/ include / net / route.h
这个方法核心就是 __ip_route_output_key .当目的地址或者源地址有其一为空,则会调用 __ip_route_output_key 填充ip地址。目的地址为空说明可能是在回环链路中通信,如果源地址为空,那个说明可能往目的地址通信需要填充本地被DDNS分配好的内网地址。
在这个方法中核心还是调用了 flowi4_init_output 进行flowi4结构体的初始化。
文件:/ include / net / flow.h
能看到这个过程把数据中的源地址,目的地址,源地址端口和目的地址端口,协议类型等数据给记录下来,之后内网ip地址的查询与更新就会频繁的和这个结构体进行交互。
能看到实际上 flowi4 是一个用于承载数据的临时结构体,包含了本次路由操作需要的数据。
执行的事务如下:
想要弄清楚ip路由表的核心逻辑,必须明白路由表的几个核心的数据结构。当然网上搜索到的和本文很可能大为不同。本文是基于LInux 内核3.1.8.之后的设计几乎都沿用这一套。
而内核将路由表进行大规模的重新设计,很大一部分的原因是网络环境日益庞大且复杂。需要全新的方式进行优化管理系统中的路由表。
下面是fib_table 路由表所涉及的数据结构:
依次从最外层的结构体介绍:
能看到路由表的存储实际上通过字典树的数据结构压缩实现的。但是和常见的字典树有点区别,这种特殊的字典树称为LC-trie 快速路由查找算法。
这一篇文章对于快速路由查找算法的理解写的很不错: https://blog.csdn.net/dog250/article/details/6596046
首先理解字典树:字典树简单的来说,就是把一串数据化为二进制格式,根据左0,右1的方式构成的。
如图下所示:
这个过程用图来展示,就是沿着字典树路径不断向下读,比如依次读取abd节点就能得到00这个数字。依次读取abeh就能得到010这个数字。
说到底这种方式只是存储数据的一种方式。而使用数的好处就能很轻易的找到公共前缀,在字典树中找到公共最大子树,也就找到了公共前缀。
而LC-trie 则是在这之上做了压缩优化处理,想要理解这个算法,必须要明白在 tnode 中存在两个十分核心的数据:
这负责什么事情呢?下面就简单说说整个lc-trie的算法就能明白了。
当然先来看看方法 __ip_dev_find 是如何查找
文件:/ net / ipv4 / fib_trie.c
整个方法就是通过 tkey_extract_bits 生成tnode中对应的叶子节点所在index,从而通过 tnode_get_child_rcu 拿到tnode节点中index所对应的数组中获取叶下一级别的tnode或者叶子结点。
其中查找index最为核心方法如上,这个过程,先通过key左移动pos个位,再向右边移动(32 - bits)算法找到对应index。
在这里能对路由压缩算法有一定的理解即可,本文重点不在这里。当从路由树中找到了结果就返回 fib_result 结构体。
查询的结果最为核心的就是 fib_table 路由表,存储了真正的路由转发信息
文件:/ net / ipv4 / route.c
这个方法做的事情很简单,本质上就是想要找到这个路由的下一跳是哪里?
在这里面有一个核心的结构体名为 fib_nh_exception 。这个是指fib表中去往目的地址情况下最理想的下一跳的地址。
而这个结构体在上一个方法通过 find_exception 获得.遍历从 fib_result 获取到 fib_nh 结构体中的 nh_exceptions 链表。从这链表中找到一模一样的目的地址并返回得到的。
文件:/ net / ipv4 / tcp_output.c
㈩ 怎样查看 Android APP 源代码
需要把反编译的apk存放到apktools同级文件夹目录下,然后运行要查看的安装包,具体操作如下:
1、首先把反编译的apk存放到apktools同级文件夹目录下,如下图所示。