1. 程式人生 > >Android 實踐:做一款可用的天氣 APP

Android 實踐:做一款可用的天氣 APP

可能很多人會問:之前已經寫過一篇博文來介紹怎麼做一款簡單的新聞APP(http://blog.csdn.net/yiwei12/article/details/71249628),為什麼還要專門一篇來介紹怎麼做一款天氣 APP,畢竟網路請求和資料處理都是大同小異的。如果真的要說差別的話,前一篇只是具備了一些基本的功能,來說明怎麼請求和處理返回的資料,但還不足與在日常生活中使用?這一篇實踐是來做一款日常可用的天氣 APP - 彼時天氣

—- 說明: 彼時天氣仿照魅族 Flyme 天氣設計
—- 在 coolWeather 的基礎上進行處理

總體思路

Created with Raphaël 2.1.0
開始有無快取?直接載入快取檔案有無網路?通過百度SDK 獲取位置OKHttp向介面請求對應位置的天氣資訊GSON 對返回的資料進行解析將返回的資料顯示並寫入快取檔案直接退出yesnoyesno

這就是總體的設計思路,至於後面其他的功能:選擇地區,更新頻率等功能可以之後再說

執行GIF

這裡寫圖片描述

之所以大幅度提前展示 GIF 圖,方便對後面佈局部分有更好的理解

步驟

  1. 宣告許可權
  2. 依賴庫
  3. 網路請求
  4. 網路解析
  5. 介面佈局
  6. 最後
  7. 完整程式碼下載地址(github)

宣告許可權

因為我們需要用到百度SDK的定位服務,所以需要先下載百度中包含基礎定位的 SDK(http://lbsyun.baidu.com/sdk/download

),解壓後,將其中的 .jar 檔案移動到 libs 資料夾中,在 main 目錄下新建一個 jniLibs,將剩下的幾個資料夾複製到裡面,點選 Sync 按鈕進行同步。 在 AndroidManifest 檔案中宣告許可權:

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name
="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <uses-permission android:name="android.permission.WAKE_LOCK" />

基本上都是 百度SDK 所需要的許可權,其中部分許可權是需要進行執行時處理的。同時還需要新增:

    <meta-data
            android:name="com.baidu.lbsapi.API_KEY"
            android:value="SmwjePIXo1eeRGbjw8QKrbncWfgi5V0f" />

        <service
            android:name="com.baidu.location.f"
            android:enabled="true"
            android:process=":remote" />

value 中填寫自己申請獲取的 Key,其他的格式都是固定的,這樣我們就可以呼叫 基礎定位 中的功能了

依賴庫

    compile 'org.litepal.android:core:1.4.1'               // 資料庫框架
    compile 'com.squareup.okhttp3:okhttp:3.4.1'            // 網路請求
    compile 'com.google.code.gson:gson:2.7'                // 網路解析
    compile 'com.github.bumptech.glide:glide:3.8.0'        // 圖片載入
    compile 'com.android.support:cardview-v7:24.2.1'       // 卡片式佈局
    compile 'com.android.support:design:24.2.1'            // Material Design中用到的依賴庫
    compile 'net.danlew:android.joda:2.9.9'                // 時間處理

網路請求

public class HttpUtil {
    public static void sendOkHttpRequest(String address, okhttp3.Callback callback){
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder().url(address).build();
        client.newCall(request).enqueue(callback);
    }
}

網路解析

這裡寫圖片描述
引數
這裡寫圖片描述
請求地址
{
    "HeWeather5": [
        {
            "alarms": [
                {
                    "level": "藍色",
                    "stat": "預警中",
                    "title": "山東省青島市氣象臺釋出大風藍色預警",
                    "txt": "青島市氣象臺2016年08月29日15時24分繼續釋出大風藍色預警訊號:預計今天下午到明天,我市北風風力海上6到7級陣風9級,陸地4到5陣風7級,請注意防範。",
                    "type": "大風"
                }
            ],
            "aqi": {
                "city": {
                    "aqi": "60",
                    "co": "0",
                    "no2": "14",
                    "o3": "95",
                    "pm10": "67",
                    "pm25": "15",
                    "qlty": "良",  //共六個級別,分別:優,良,輕度汙染,中度汙染,重度汙染,嚴重汙染
                    "so2": "10"
                }
            },
            "basic": {
                "city": "青島",
                "cnty": "中國",
                "id": "CN101120201",
                "lat": "36.088000",
                "lon": "120.343000",
                "prov": "山東"  //城市所屬省份(僅限國內城市)
                "update": {
                    "loc": "2016-08-30 11:52",
                    "utc": "2016-08-30 03:52"
                }
            },
            "daily_forecast": [
                {
                    "astro": {
                        "mr": "03:09",
                        "ms": "17:06",
                        "sr": "05:28",
                        "ss": "18:29"
                    },
                    "cond": {
                        "code_d": "100",
                        "code_n": "100",
                        "txt_d": "晴",
                        "txt_n": "晴"
                    },
                    "date": "2016-08-30",
                    "hum": "45",
                    "pcpn": "0.0",
                    "pop": "8",
                    "pres": "1005",
                    "tmp": {
                        "max": "29",
                        "min": "22"
                    },
                    "vis": "10",
                    "wind": {
                        "deg": "339",
                        "dir": "北風",
                        "sc": "4-5",
                        "spd": "24"
                    }
                }
            ],
            "hourly_forecast": [
                {
                    "cond": {
                        "code": "100",
                        "txt": "晴"
                    },
                    "date": "2016-08-30 12:00",
                    "hum": "47",
                    "pop": "0",
                    "pres": "1006",
                    "tmp": "29",
                    "wind": {
                        "deg": "335",
                        "dir": "西北風",
                        "sc": "4-5",
                        "spd": "36"
                    }
                }
            ],
            "now": {
                "cond": {
                    "code": "100",
                    "txt": "晴"
                },
                "fl": "28",
                "hum": "41",
                "pcpn": "0",
                "pres": "1005",
                "tmp": "26",
                "vis": "10",
                "wind": {
                    "deg": "330",
                    "dir": "西北風",
                    "sc": "6-7",
                    "spd": "34"
                }
            },
            "status": "ok",
            "suggestion": {
                "comf": {
                    "brf": "較舒適",
                    "txt": "白天天氣晴好,您在這種天氣條件下,會感覺早晚涼爽、舒適,午後偏熱。"
                },
                "cw": {
                    "brf": "較不宜",
                    "txt": "較不宜洗車,未來一天無雨,風力較大,如果執意擦洗汽車,要做好蒙上汙垢的心理準備。"
                },
                "drsg": {
                    "brf": "熱",
                    "txt": "天氣熱,建議著短裙、短褲、短薄外套、T恤等夏季服裝。"
                },
                "flu": {
                    "brf": "較易發",
                    "txt": "雖然溫度適宜但風力較大,仍較易發生感冒,體質較弱的朋友請注意適當防護。"
                },
                "sport": {
                    "brf": "較適宜",
                    "txt": "天氣較好,但風力較大,推薦您進行室內運動,若在戶外運動請注意防風。"
                },
                "trav": {
                    "brf": "適宜",
                    "txt": "天氣較好,風稍大,但溫度適宜,是個好天氣哦。適宜旅遊,您可以盡情地享受大自然的無限風光。"
                },
                "uv": {
                    "brf": "強",
                    "txt": "紫外線輻射強,建議塗擦SPF20左右、PA++的防晒護膚品。避免在10點至14點暴露於日光下。"
                }
            }
        }
    ]
}
返回型別示例

我們後面申請資料採用的引數都為 城市名稱,從返回示例中我們可以看出,結構和我們上次新聞API 返回的結構是有差異的,多嵌套了一層,不過 GSON 解析的方式還是一樣的。在包名下新建一個 gson 資料夾,在裡面新建對應資料的實體類:

AQI.class

public class AQI {

    public AQICity city;

    public class AQICity{
        public String aqi;
        public String pm25;
        public String co;
        public String o3;
        public String pm10;
        public String so2;
    }
}

Basic.class

public class Basic {
    @SerializedName("city")
    public String cityName;

    @SerializedName("id")
    public String weatherId;

    public  Update update;

    public class Update{
        public String loc;

    }


}

Forecast.class

public class Forecast {

    public String date;

    @SerializedName("tmp")
    public Temperature temperature;

    @SerializedName("cond")
    public More more;

    public class More{
        @SerializedName("txt_d")
        public String info;

        @SerializedName("code_d")
        public int code;
    }

    public class Temperature{
        public String max;
        public String min;
    }

}

Hourly.class

public class Hourly {

    public Cond cond;

    public class Cond{

        public String code;

        public String txt;

    }

    public String date;

    public String tmp;
}

Now.class

public class Now {
    @SerializedName("tmp")
    public String temperature;

    @SerializedName("cond")
    public More more;

    public class More{
        @SerializedName("txt")
        public String info;
    }

}

Suggestion.class

public class Suggestion {
    @SerializedName("comf")
    public Comfort comfort;

    @SerializedName("cw")
    public CarWash carWash;

    public Sport sport;

    @SerializedName("drsg")
    public Clothes clothes;

    @SerializedName("flu")
    public Cold cold;


    public UV uv;

    public class UV{
        @SerializedName("txt")
        public String info;

        @SerializedName("brf")
        public String sign;
    }

    public class Cold{
        @SerializedName("txt")
        public String info;

        @SerializedName("brf")
        public String sign;
    }

    public class Clothes{
        @SerializedName("txt")
        public String info;

        @SerializedName("brf")
        public String sign;
    }

    public class Comfort{
        @SerializedName("txt")
        public String info;

        @SerializedName("brf")
        public String sign;
    }

    public class CarWash{
        @SerializedName("txt")
        public String info;

        @SerializedName("brf")
        public String sign;
    }

    public class Sport{
        @SerializedName("txt")
        public String info;

        @SerializedName("brf")
        public String sign;
    }
}

最後就是返回資料的對應實體類 Weather.class

public class Weather {

    public String status;

    public Basic basic;

    public AQI aqi;

    public Now now;

    public Suggestion suggestion;

    @SerializedName("daily_forecast")
    public List<Forecast> forecastList;

    @SerializedName("hourly_forecast")
    public List<Hourly> hourlyList;
}

在包名下新建目錄 util , 在其中新建類:Utility.class

public class Utility {
    /**
     *
     * 處理得到的 weather 資料,轉化為 weather 物件
     */
    public static Weather handleWeatherResponse(String response){
        try{
            JSONObject jsonObject = new JSONObject(response);
            JSONArray jsonArray = jsonObject.getJSONArray("HeWeather5");
            String weatherContent = jsonArray.getJSONObject(0).toString();
            return new Gson().fromJson(weatherContent, Weather.class);
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

}

介面佈局

相信大家都看了執行的 GIF 圖,可以看到主介面的佈局還是比較繁瑣的,所以引入佈局不失為一個好的選擇,主介面佈局主要分為以下幾個部分:

weather_title(標題欄)
weather_now(當前天氣資訊)
weather_hourly(小時天氣預報)
weather_forecast(未來幾天的天氣預報)
weather_aqi(空氣質量)
weather_suggestion(生活建議)

以下是各部分的程式碼:

weather_title:

<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:background="@color/colorWhite"
    app:popupTheme="@style/ToolbarPopupTheme"
    app:subtitleTextColor="@color/colorFont">

    <TextView
        android:id="@+id/title_city"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:textColor="@color/colorFont"
        android:textSize="20sp"/>


</android.support.v7.widget.Toolbar>

Toolbar 中間放置了 title_city ,用來顯示當前的城市名

weather_now

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="400dp"
    android:background="@color/colorWhite">


    <RelativeLayout
        android:id="@+id/weather_now_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/colorWhite">

        <TextView
            android:id="@+id/degree_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:gravity="center"
            android:textColor="@color/colorFont"
            android:textSize="120sp"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@+id/degree_text"
            android:layout_alignTop="@+id/degree_text"
            android:text="°"
            android:textColor="@color/colorFont"
            android:textSize="120sp"
            />

        <TextView
            android:id="@+id/weather_info_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_above="@+id/degree_text"
            android:layout_centerHorizontal="true"
            android:textColor="@color/colorFont"
            android:textSize="20sp"/>

        <TextView
            android:id="@+id/update_time_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/degree_text"
            android:layout_centerHorizontal="true"
            android:textColor="@color/colorFont"
            android:textSize="12sp"/>



    </RelativeLayout>

</RelativeLayout>

在檢視中間,從上至下放置了三個TextView 控制元件:weather_info_text(天氣狀況),degree_text(天氣溫度),update_time_text(資料更新時間),另外一個“°”符號放在溫度的右上角

weather_hourly:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="100dp"
    android:background="@color/colorWhite">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/weather_hourly"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"/>


</LinearLayout>

為了支援小時天氣預報部分可以直接水平滑動(不過免費使用者可以得到的資料量好像不需要滑動 2333333),放置了一個 RecyclerView

weather_hourly_item

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="80dp"
    android:layout_height="100dp"
    android:padding="10dp">

    <TextView
        android:id="@+id/hour_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/colorFont"
        android:layout_centerInParent="true"
        android:textSize="14sp"/>

    <TextView
        android:id="@+id/hour_degree"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/colorFont"
        android:textSize="14sp"
        android:layout_below="@+id/hour_text"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="4dp"/>

    <TextView
        android:id="@+id/hout_time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/colorFont"
        android:textSize="14sp"
        android:layout_above="@+id/hour_text"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="4dp"/>


</RelativeLayout>

小時天氣預報的每個子項中,從上到下放置了三個TextView控制元件:hour_degree(天氣溫度),hour_text(天氣描述),hout_time(時間)

weather_forecast:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/colorWhite">


    <LinearLayout
        android:id="@+id/forecast_layout"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    </LinearLayout>


</LinearLayout>

這裡採用的還是原方案,直接設定一個 LinearLayout 佈局,後面直接在其中新增子佈局,當然,大家也可以選用一個 ListView 來顯示內容

weather_forecast_item

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="15dp">

    <TextView
        android:id="@+id/data_text"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:layout_gravity="center_vertical"
        android:gravity="left"
        android:textColor="@color/colorFont"
        />

    <LinearLayout
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="wrap_content">

        <ImageView
            android:id="@+id/weather_pic"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical|right"/>

        <TextView
            android:id="@+id/info_text"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:layout_marginLeft="15dp"
            android:layout_gravity="center_vertical|left"
            android:textColor="@color/colorFont"
            android:gravity="left"
            />

    </LinearLayout>

    <TextView
        android:id="@+id/max_min_text"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:gravity="right"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:textColor="@color/colorFont"
        />




</LinearLayout>

子項中水平放置了四個控制元件:data_text(預報日期),weather_pic(天氣圖片),info_text(天氣資訊),max_min_text(當天溫度)

weather_aqi:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="75dp">

        <RelativeLayout
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent"
            android:background="@color/colorWhite"
            >

            <TextView
                android:id="@+id/aqi_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:textColor="@color/colorFont"
                android:layout_centerInParent="true"
                android:textSize="18sp"/>

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:layout_below="@+id/aqi_text"
                android:text="AQI 指數"
                android:textSize="10sp"
                android:textColor="@color/colorFont"/>

        </RelativeLayout>


        <RelativeLayout
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent"
            android:background="@color/colorWhite">

            <TextView
                android:id="@+id/pm25_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:textColor="@color/colorFont"
                android:textSize="18sp"/>

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:layout_below="@+id/pm25_text"
                android:text="PM2.5 指數"
                android:textSize="10sp"
                android:textColor="@color/colorFont"/>


        </RelativeLayout>


        <RelativeLayout
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent"
            android:background="@color/colorWhite">

            <TextView
                android:id="@+id/co_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:textColor="@color/colorFont"
                android:textSize="18sp"/>

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:layout_below="@+id/co_text"
                android:text="CO 指數"
                android:textSize="10sp"
                android:textColor="@color/colorFont"/>


        </RelativeLayout>


    </LinearLayout>


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="75dp">

        <RelativeLayout
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent"
            android:background="@color/colorWhite">

            <TextView
                android:id="@+id/o3_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:textColor="@color/colorFont"
                android:textSize="18sp"/>

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:layout_below="@+id/o3_text"
                android:text="O3 指數"
                android:textSize="10sp"
                android:textColor="@color/colorFont"/>

        </RelativeLayout>


        <RelativeLayout
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent"
            android:background="@color/colorWhite">

            <TextView
                android:id="@+id/pm10_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:textColor="@color/colorFont"
                android:textSize="18sp"/>

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:layout_below="@+id/pm10_text"
                android:text="PM10 指數"
                
            
           

相關推薦

Android 實踐可用天氣 APP

可能很多人會問:之前已經寫過一篇博文來介紹怎麼做一款簡單的新聞APP(http://blog.csdn.net/yiwei12/article/details/71249628),為什麼還要專門一篇來介紹怎麼做一款天氣 APP,畢竟網路請求和資料處理都是大同小異

Android 實踐新聞 APP

跟程式碼相關的工作,大多唯手熟爾,所以這裡花了點時間做了款簡易版的新聞 APP,雖然都是些基礎的內容,不過還是可以加深自己對部分程式碼的理解。至少,可以加深自己的記憶 步驟 依賴庫 網路請求 網路解析 介面佈局 最後 執行介面 執行GIF 完整程式

阿里開發者們的第15個感悟優秀大資料引擎,要找準重點解決的業務場景

1月10日,做一款優秀大資料引擎,要找準重點解決的業務場景。這是我們送給開發者的第15個感悟。 沐遠在社群分享了他的博文,《使用spark分析雲HBase的資料》《hive資料匯入雲hbase》,粉絲評論說請收下我的膝蓋。 李偉(沐遠)阿里雲資料庫技術專家專注大資料分散式計算資料庫領域, 研發Spark及

阿裏開發者們的第15個感悟優秀大數據引擎,要找準重點解決的業務場景

數據 base 開發者 alt 優秀 ces log 理解 社區 1月10日,做一款優秀大數據引擎,要找準重點解決的業務場景。這是我們送給開發者的第15個感悟。 沐遠在社區分享了他的博文,《使用spark分析雲HBase的數據》《hive數據導入雲hbase》,粉絲評論說請

Android自定義EditText手把手教你鍵刪除&自定義樣式的SuperEditText

前言 Android開發中,EditText的使用 非常常見 本文將手把手教你做一款 附帶一鍵刪除功能 & 自定義樣式豐富的 SuperEditText控制元件,希望你們會喜歡。 目錄 1. 簡介 一款 附帶一鍵刪除功

Android開發者必備推薦助力開發的開源APP

今天,給大家推薦一款小而精的開源應用,該應用是同事推薦給我的,我使用後感覺不錯遂在這兒分享給大家。 我們都知道,當我們新接觸一個 Android 專案想要快速熟悉程式碼時,最好的方式就是執行起來,從看得見的入手,一點點去除錯、捋程式碼。而事實上,大多數公司沒有那麼多時間讓你花幾天時間慢慢看,基本

Android-live如何利用第三方SDK直播軟體

SDK服務選擇 目前有很多做直播雲的服務 樂視雲 網易雲信 保利威視 阿里雲 百度雲 可以根據自己的需要做選擇。 直播基本原理 Push推流 也就是直播端,用於採集視訊資訊上傳,處理等。 Pull拉流 使用者實時播放直播的視訊源 服務端

Android開源實戰使用MVP+Retrofit開發文字閱讀APP

文字控 使用MVP+Retrofit開發的一款文藝APP,它是一個非常優美的文字閱讀應用,介面基本上符合material design設計規範。 在該專案中,我採用的是MVP架構,該架構目前在Android開發中非常流行,但MVP並不是一個標準,它只是一種思想

[轉]個人開發者Android App需要知道的事情

原文連結:https://www.cnblogs.com/hubcarl/p/4030884.html目前,應用資訊型別App功能核心都包括內容列表展示、內容詳情展示、個人中心、 評論分享、搜尋四大功能。下面就我以我開發的一款程式設計學習的App[程式設計線上]為例, UI

談毛豆鋼材進銷存管理系統長沙專門為鋼材經銷商和鋼材生產企業設計開發的鋼材類軟件

長沙毛豆科技 毛豆鋼材進銷存管理系統 長沙軟件開發 毛豆鋼材進銷存管理系統:專門為鋼材經銷商和鋼材生產企業設計開發的鋼材類軟件 長沙毛豆科技小編給大家介紹“毛豆鋼材進銷存管理系統”的基本功能:毛豆鋼材進銷存管理系

.NET 逆向Patch 實時日誌查看軟件

github 修改 由於 ipa 發現 ply class 技術分享 優勢 我的第一個逆向作品,和大家分享。 一款我很喜歡的實現日誌查看軟件,官網:https://www.logfusion.ca/。 個人感覺和免費的如logExpert相比,最大的優勢就是高分支持做的比較

Android 開發)安卓開發環境搭建與配置 (Windows和Mac )以及目錄結構介紹

(一)、windows版 一. 開發工具: 1.Android Studio:(http://www.androiddevtools.cn/) 2.Genymotion(虛擬機器):(http://www.genymotion.net/) (二)、Mac版 一

跨平臺(多家soC平臺)多特性元件化IPC軟體

構想:為IP攝像機定做一款軟體,先基於GM/TI/Hisi平臺,未來會相容更多平臺。名稱叫:IPC-Guarder IPC-guarder將實現如下功能: Funcitions list: Liveview:local liveview(BNC out), network liveview

提高Android開發效率的自動findViewById和設定監聽的實用外掛

今天來講一個外掛LayoutCreator,有了這個外掛,無疑,在開發中效率會大大提升... 下載後,重啟AS即可 介紹使用方法: 1.選中Activity所在的佈局右鍵; 選中LyoutCreator 點選後,可以發現,該外掛已經為我們找到控制元件id了(可以

【原創】關於視訊播放器如何做到邊播邊快取?【如何用Vitamio功能強大的視訊播放器補充篇】

上一篇介紹了怎樣做一款功能強大的視訊播放器,是基於Vitamio框架開發的。這裡我們再補充一個功能:如何做到視訊邊播放邊快取到本地? 這個需求還挺常見的。由於使用者的網路環境複雜,經常會有網速較慢看視訊時卡頓、緩衝的現象,並且有時候我們需要頻繁的拖拽進度條,如果播放的是

教你可以賺錢的iPhone APP》02

首先介紹一下開發一款蘋果手機的APP需要的工具 1.     需要一臺裝有蘋果系統(Mac系統)的電腦。如下的電腦均可: iMac Mac Pro MacBook Mac mini 2.     軟體Xcode。 安裝方法: 開啟Mac系統裡自帶的Ap

教你可以賺錢的iPhone APP》03

第1部分 故事的基礎要素 - 程式語言的基礎部分 故事的基礎要素一般包括文字,語句,標點符號等。與之類似,我們這一部分介紹程式語言Swift的基礎部分。 1 變數與常量  1.1 概念通俗講解  變數是指可以變化的量。常量是指不可以變化的量。  以人舉例,人的性

教你可以賺錢的iPhone APP》22

第2部分 故事的進階要素 - 程式語言Swift的進階部分 10 方法 10.1 概念通俗講解 方法是一種特殊的函式,在類或者結構體裡的函式叫方法。其實方法的本質就是函式,只不過它是在類裡,結構體裡使用

教你可以賺錢的iPhone APP》25

第2部分 故事的進階要素 - 程式語言Swift的進階部分 13 擴充套件 13.1 概念通俗講解 擴充套件的作用是為已存在的類、結構體、列舉或者協議型別新增新的功能。 例如,String是一個結構體,

教你可以賺錢的iPhone APP》28

第2部分 故事的進階要素 - 程式語言Swift的進階部分 16 委託 16.1 概念通俗講解 委託是一種設計模式,它使類或結構體通過協議能夠將其某些職責委託給另一個類或結構體,讓另一個類或結構體幫它實