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同級文件夾目錄下,如下圖所示。