一次重拾Android Studio開發的經歷

版權聲明:本文爲博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/Holdrenminbi/article/details/81023042

一次重拾Android Studio開發的經歷

作爲一個非專業碼農,有時候必須要穿梭於不同的編程語言之間,近來再次編完單片機,又去編上位機!沒有隊友的時候只能自己上,也比有一堆豬隊友強!

  • 前言
  • 正題
  • 解決辦法

前言

由於近來閒來無事,就打算搞搞事情,恰巧有個機會,有個同學的項目有進展,他們沒有人會寫Code,這事情只能落到我頭上(這是個悲劇!)。其主要算是一個簡單的小型化設備,用到的模塊也是比較的簡單,就應下了。主要用到的模塊有RC522無線射頻模塊(就是同學們食堂餐廳刷的卡)、串口觸摸屏、串口打印機、ESP8266WiFi模塊。總體來說,這些模塊還是相對簡單,有用到的可以在網上搜索相關代碼即可,強調下就是ESP8266最好是用別人調試好的相對比較系統的代碼,用起來非常方便!

進入正題

前面囉嗦的是這件事的前提,就是先寫完了,單片機代碼,又來寫手機端代碼的!本來打算交給別人來寫的,但是對方不給幹事,我脾氣一上來就重新操刀,擼起袖子自己來幹!

第一次接觸安卓開發還是2015年的事,當時在大城市看着自己的專業根本就是不掙錢(生存的資本),趕着最火的時候發奮圖強學一波,自己當時的底子僅僅是C語言,根本就只是聽說過面向對象而已,也是對自己下了狠勁才學的。
當時的電腦I5配置,2G內存,機械硬盤,安裝個Android Studio + Genymotion 分分鐘卡住不能動彈(後來加成4G內存也是卡,當時也是拮据,也是不知道什麼是SSD)
經過這幾年的成長,Code能力算是見長,只是沒有太多的機會寫Java,不過編程是相通的,只要是能夠掌握要領,還是蠻快的。

基本思路

  • 第一步:安裝Android Studio
  • 第二步:安裝Genymotion模擬器
  • 第三步:開始幹吧

第一步:安裝Android Studio(非常簡單)

之前在安裝Android Studio都是通過國內一些大學等等鏡像安裝,現在安裝已經非常方便了,直接去官網下載就可以了。
ps:我用Android Studio也是因爲當時自己在安裝Eclips時候遇到了很多的教程和很多的困難,一直沒解決,當時也是正好Android Studio剛出來的時候,教程多而且非常詳細,就選了。唯一的問題就是當時gradle經常莫名的出錯。

第二步:Genymotion模擬器(也是非常簡單)

簡單在Genymotion註冊下載安裝帶Virtual Box的即可。再選擇SDK路徑,到AS中連接,重啓一般都可以發現。

第三步:開始幹吧(難點)

由於之前一直在接觸C#,對於其便捷的界面開發非常滿意,而Android Studio也有非常實用的界面預覽,就從這點出發開始寫。(由於本次Project相對功能簡單,就走了這樣的路子)

佈局界面

這裏寫圖片描述
在創建Project的時候,Android Studio 會指引建立界面,如登錄界面、空界面等等。界面佈局方面,AS也是非常的簡單直觀,簡單列出了一些非常常用到的控件,這一點與Visual Studio相似,根據需要拖動即可,其他實用控件,網上有第三方開源,MPChart(本次用到的控件,後面會細講)。
ps:我遇到的問題,如果不能很好地看到預覽界面,需要修改res/values/styles.xml文件中name=“AppTheme”的style,Theme.AppCompat.Light.DarkActionBar前面添加Base.
根據創建的界面,在模擬器安裝完成的前提下,就可以直接運行,,一般就是你選着的界面或者hello world.

跳轉新窗口並跳轉

1,創建layout(activity_new.xml)
在src/main/res/layout鼠標右鍵
new->LayoutResource File
然後輸入一個file name,比如:activity_new
點ok鍵完成創建

2,創建activity(newActivity.Java)

src/main/java/com.example.test鼠標右鍵

new->java class

然後輸入一個name,比如,newActivity

kind選擇class

點ok鍵完成創建

進入剛創建的OtherActivity.java文件在onCreate方法內增加 setContentView(R.layout.activity_other);用來指向我們剛創建的名爲activity_other的layout

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

public class newActivity extends AppCompatActivity {

public void onCreate(BundlesavedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_new);
}

}

3,跳轉到第剛創建的newActivity

在按鈕事件增加以下代碼,

    Intent intent = new Intent();
    intent.setClass(MainActivity.this, newActivity.class);
    MainActivity.this.startActivity(intent);

這裏紅色部分的TestActivity是我放按鈕的activity的類名,也就是第一個activity的類的名字

跳轉頁可以縮小成一句:

startActivity(new Intent(MainActivity.this, newActivity.class));//紅色部分爲要打開的新窗口的類名

4.配置androidManifest,在application裏面添加otherActivity的信息

   <application

    android:allowBackup="true"

   android:icon="@mipmap/ic_launcher"

   android:label="@string/app_name"

   android:supportsRtl="true"

   android:theme="@style/AppTheme">

    <activityandroid:name=".MainActivity">

       <intent-filter>

           <action android:name="android.intent.action.MAIN" /> 

           <category android:name="android.intent.category.LAUNCHER" />

       </intent-filter>

    </activity>

    <activityandroid:name=".newActivity"></activity>

</application>

Activity傳值

A-B之間數據傳遞

1)單向傳值:A傳值給B,但不需要B返回數據
A:

//傳入數據給B
Intent i = new Intent(A.this,B.class);
i.putExtra("A_B","給B的數據");
startActivity(i);

B:

//拿到A傳入的數據
String date= getIntent().getStringExtra("A_B");

2)雙向傳值:A傳值給B,並且需要B返回數據給A
A:

//傳入數據給B
Intent i = new Intent(A.this,B.class);
i.putExtra("A_B","給B的數據");
startActivityForResult(i, 0x123);

//接收B返回的數據,重寫onActivityResult方法
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//判斷返回的code是否是B頁面的code
if(resultCode==0x123){
//拿到B傳回的數據
String date = intent.getStringExtra("B_A");
}
   }

B:

//接收A傳入的數據
String date= getIntent().getStringExtra("A_B");

//返回數據給A,在末尾一定要將當前頁面finish
Intent intent = new Intent();
intent.putExtra("B_A","返回給A的數據");
setResult(0x123,intent);
onBackPressed();

B-C,A-C之間的數據單向或者雙向傳遞都跟A-B之間數據傳遞的方法一樣,這裏就不重複寫了,有興趣的同學可以把代碼寫一遍跑一下,下面說說C跳過B直接傳遞值給A怎麼做。

A->B->C,C->A

在實際應用開發中有很多情況是A->B->C,然後在C中做了某些操作,需要把一些值直接跳過B直接傳遞給A,其實這種傳值方式同樣有很多種,比如發個特定的廣播,循環退出已經存在的頁面等等,其實方法有很多種,下面我還是以Intent傳值爲例
C:

 Intent i = new Intent(C.this, A.class);
 i.putExtra("C_A", "C傳回給A的數據");

//要啓動的activity已經在當前的任務中,那麼在該activity之上的activity都會關閉,並且intent會傳遞給在棧頂的activity

//如果 Activity 已經是運行在 Task 的 top,則該 Activity 將不會再被啓動

 i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
 startActivity(i);

A:

此時需要在A中重寫onNewIntent方法,在該方法中獲取從C中傳遞的值

   @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
  //從C返回的數據
 String date = intent.getStringExtra("C_A");
}

創建菜單Menu

android一共有三種形式的菜單:
1.選項菜單(optinosMenu)
2.上下文菜單(ContextMenu)
3.子菜單(subMenu)
其中最常用的就是選項菜單(optionsMenu), 該菜單在點擊 menu 按鍵 後會在對應的Activity底部顯示出來。
1.Activity菜單機制 (與dialog類似)
Activity有一套機制來實現對菜單的管理,方法如下:

public class MainActivity extends Activity {

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }

        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            /**
             * 此方法用於初始化菜單,其中menu參數就是即將要顯示的Menu實例。 返回true則顯示該menu,false 則不顯示;
             * (只會在第一次初始化菜單時調用) Inflate the menu; this adds items to the action bar
             * if it is present.
             */
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }

        @Override
        public boolean onPrepareOptionsMenu(Menu menu) {
            /**
             * 在onCreateOptionsMenu執行後,菜單被顯示前調用;如果菜單已經被創建,則在菜單顯示前被調用。 同樣的,
             * 返回true則顯示該menu,false 則不顯示; (可以通過此方法動態的改變菜單的狀態,比如加載不同的菜單等) TODO
             * Auto-generated method stub
             */
            return super.onPrepareOptionsMenu(menu);
        }

        @Override
        public void onOptionsMenuClosed(Menu menu) {
            /**
             * 每次菜單被關閉時調用. (菜單被關閉有三種情形,menu按鈕被再次點擊、back按鈕被點擊或者用戶選擇了某一個菜單項) TODO
             * Auto-generated method stub
             */
            super.onOptionsMenuClosed(menu);
        }

        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            /**
             * 菜單項被點擊時調用,也就是菜單項的監聽方法。 
             * 通過這幾個方法,可以得知,對於Activity,同一時間只能顯示和監聽一個Menu 對象。 TODO Auto-generated
             * method stub
             */
            return super.onOptionsItemSelected(item);
        }
}

. 添加菜單:
可以在onCreateOptionsMenu或者 onPrepareOptionsMenu方法中來添加菜單

2.1代碼添加:
menu.add((int groupId, int itemId, int order, charsequence title) .setIcon(drawable ID)

   add()方法的四個參數,依次是: 

  1、組別,如果不分組的話就寫Menu.NONE, 

  2、Id,這個很重要,Android根據這個Id來確定不同的菜單 

  3、順序,哪個菜單項在前面由這個參數的大小決定 

  4、文本,菜單項的顯示文本

   add()方法返回的是MenuItem對象,調用其setIcon()方法,爲相應MenuItem設置Icon 
 示例: 
public boolean onCreateOptionsMenu(Menu menu) { 
    super.onCreateOptionsMenu(menu); 
    menu.add(Menu.NONE,  Menu.First+1 , 0, "設置").setIcon(R.drawable.setting); 
    return true; 
} 

2.2佈局文件添加:

   getMenuInflater().inflate(R.menu.options_menu, menu); 
  調用Activity的getMenuInflater()得到一個MenuInflater,  
   使用inflate方法來把佈局文件中的定義的菜單 加載給 第二個參數所對應的menu對象 
   示例: 
 @Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    super.onCreateOptionsMenu(menu); 
    getMenuInflater().inflate( R.menu.options_menu , menu); 
    return true; 
} 
佈局文件: 
  在res目錄下建立一個menu文件夾,並創建佈局文件: options_menu.xml  
<?xml version="1.0" encoding="utf-8"?> 
<menu xmlns:android="http://schemas.android.com/apk/res/android"> 
<item android:id=" @+id/menu_setting " android:title="設置" android:icon="@drawable/setting"></item> 
</menu> 

3.菜單項監聽:
只要菜單中的菜單項被點擊,都會觸發onOptionsItemSelected(MenuItem item)
item參數即爲被點擊的菜單項,那麼需要在此方法內判斷哪個Item被點擊了,從而實現不同的操作。
對於兩種不同的添加菜單方法,判斷的方法有一點區別,但本質是一樣的。

 @Override 
public boolean onOptionsItemSelected(MenuItem item) { 
    super.onOptionsItemSelected(item); 
    switch(item.getItemId()) //得到被點擊的item的itemId 
    { 
    case  Menu.First+1 :  //對應的ID就是在add方法中所設定的Id 
        break; 
    case  Menu.First+2 : 
        break; 
    } 
    return true; 
} 

3.2佈局文件添加菜單的判斷方法:

@Override 
public boolean onOptionsItemSelected(MenuItem item) { 
    super.onOptionsItemSelected(item); 
    switch(item.getItemId()) //得到被點擊的item的itemId 
    { 
    case  R.id.menu_setting : //這裏的Id就是佈局文件中定義的Id,在用R.id.XXX的方法獲取出來 
        break; 
    case R.id.menu_info: 
        break; 
    } 
    return true; 
}

創建網絡連接

最好是在網上找個比較靠譜實用的Socket,這裏我沒找到好用的,就不亂放代碼及浪費時間了

手機網絡連接(未測試)

1、所需權限

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>  
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>  
<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission> 
<uses-permission android:name="android.permission.INTERNET"></uses-permission> 

2、代碼

/**
     * 獲取IP
     * @param context
     * @return
     */
     public static String getIp(final Context context) {
         String ip = null;
            ConnectivityManager conMan = (ConnectivityManager) context
                    .getSystemService(Context.CONNECTIVITY_SERVICE);

        // mobile 3G Data Network
        android.net.NetworkInfo.State mobile = conMan.getNetworkInfo(
                ConnectivityManager.TYPE_MOBILE).getState();
        // wifi
        android.net.NetworkInfo.State wifi = conMan.getNetworkInfo(
                ConnectivityManager.TYPE_WIFI).getState();

        // 如果3G網絡和wifi網絡都未連接,且不是處於正在連接狀態 則進入Network Setting界面 由用戶配置網絡連接
        if (mobile == android.net.NetworkInfo.State.CONNECTED
                || mobile == android.net.NetworkInfo.State.CONNECTING) {
            ip =  getLocalIpAddress();
        }
        if (wifi == android.net.NetworkInfo.State.CONNECTED
                || wifi == android.net.NetworkInfo.State.CONNECTING) {
              //獲取wifi服務  
            WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);  
            //判斷wifi是否開啓  
            if (!wifiManager.isWifiEnabled()) {  
            wifiManager.setWifiEnabled(true);    
            }  
            WifiInfo wifiInfo = wifiManager.getConnectionInfo();       
            int ipAddress = wifiInfo.getIpAddress();   
            ip =(ipAddress & 0xFF ) + "." +       
                    ((ipAddress >> 8 ) & 0xFF) + "." +       
                    ((ipAddress >> 16 ) & 0xFF) + "." +       
                    ( ipAddress >> 24 & 0xFF) ;    
        }
        return ip;

    }

 /**
  * 
  * @return 手機GPRS網絡的IP
  */
    private static String getLocalIpAddress()  
    {  
         try {
             //Enumeration<NetworkInterface> en=NetworkInterface.getNetworkInterfaces();
             for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
                 NetworkInterface intf = en.nextElement();
                 for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
                     InetAddress inetAddress = enumIpAddr.nextElement();
                     if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {//獲取IPv4的IP地址
                         return inetAddress.getHostAddress();
                     }
                 }
             }
         } catch (SocketException e) {
             e.printStackTrace();
         }

        return null;  
 }  

第三方圖表類 MPAndroidChart 的使用

網上一個比較好用的開源圖表類擴展 附上開源地址:
https://github.com/PhilJay/MPAndroidChart
https://bng86.gitbooks.io/android-third-party-/content/mpandroidchart.html
簡單在網上找了相關的示例圖片感覺很不錯,感興趣的朋友可以自行搜索參閱

這裏寫圖片描述
網上講的都是大同小異,不過好多都講的並不是非常的好,能簡單實現,在具體設置最好了,於是乎經人指點在網上找到了下面這個網址,非常合適。
https://www.numetriclabz.com/android-line-chart-using-mpandroidchart-tutorial/

這裏寫圖片描述

具體方法如下:
第一步:下載jar文件,放在libs文件夾中;
第二步:在build.gradle中添加如下代碼

        repositories {<br />
                    maven { url &quot;https://jitpack.io&quot; }<br />
            }</p>
    <p>dependencies {<br />
        compile 'com.github.PhilJay:MPAndroidChart:v2.1.6'<br />
    }<br />

第三步:在layout文件夾中添加Linechart等

    <br />
 &lt;com.github.mikephil.charting.charts.LineChart<br />
            android:id=&quot;@+id/chart&quot;<br />
            android:layout_width=&quot;match_parent&quot;<br />
            android:layout_height=&quot;300dp&quot; /&gt;</p>
<p>

第四步:創建指向性的實例與數據集

<br />
   LineChart lineChart = (LineChart) findViewById(R.id.chart);<br />
        // creating list of entry<br />
        ArrayList&lt;Entry&gt; entries = new ArrayList&lt;&gt;();<br />
        entries.add(new Entry(4f, 0));<br />
        entries.add(new Entry(8f, 1));<br />
        entries.add(new Entry(6f, 2));<br />
        entries.add(new Entry(2f, 3));<br />
        entries.add(new Entry(18f, 4));<br />
        entries.add(new Entry(9f, 5));</p>
<p>
<br />
 LineDataSet dataset = new LineDataSet(entries, &quot;# of Calls&quot;);<br />

第五步:設置標籤

<br />
// creating labels<br />
  ArrayList&lt;String&gt; labels = new ArrayList&lt;String&gt;();<br />
        labels.add(&quot;January&quot;);<br />
        labels.add(&quot;February&quot;);<br />
        labels.add(&quot;March&quot;);<br />
        labels.add(&quot;April&quot;);<br />
        labels.add(&quot;May&quot;);<br />
        labels.add(&quot;June&quot;);</p>
<p>

第六步:綁定數據

<br />
LineData data = new LineData(labels, dataset);<br />
lineChart.setData(data); // set the data and list of lables into chart<br />

第七步:設置圖表描述

<br />
lineChart.setDescription(&quot;Description&quot;);  // set the description<br />

一般到這裏即可debug程序,顯示如下圖:
這裏寫圖片描述

最後,可以根據自己傳遞的數據更新數據集中的數據與顯示;

總結

寫在最後

算是一次歷經坎坷,終於完成的android開發,因爲後續沒有繼續開發,就沒有進行太多的適配和優化,基本功能完善即可

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章