【Android】22.0 許可權處理(四)——應用程式版本控制:Git的使用
1.0 當然,其實本篇和許可權處理沒有什麼關係。但是:
我們需要用到上一篇博文中ProviderTest專案來當小白鼠,當然,這個專案能不能執行,無所謂。
連結在此:【Android】21.0 許可權處理(三)——訪問其他程式資料:提供資料給別的程式使用
備註:本篇內容獨立,與上篇沒有任何關係,事實上你可以用任何一個專案來操作,下面會先把這個ProviderTest專案的程式碼貼出來,所以事實上不需要去管ProviderTest專案是幹嘛的。
2.0 Git:分散式版本控制系統
百度百科連結:GIT (分散式版本控制系統)
備註: Git
的“親爹”是linux
作業系統的“親爹”——林納斯·託瓦茲(Linus Torvalds),所以,不只是Android開發,Git能用到的地方很多……
再備註: Git
就是開發時,用來方便你控制自己寫的“山寨QQ”
軟體現在是1.0版本
還是2.0版本
,然後還可以查到1.0
幹了什麼,2.0
相對於1.0
修改了什麼,還可以回滾到1.0版本
(覺得我這話還是沒法理解的,請往上走去找度娘)
再再備註: 有了Git
,很簡單就可以實現——多人同時開發一個專案。
3.0 對,你的感覺沒錯,Git是需要另外安裝的,它是一個軟體。
Windows
和linux
安裝網上都有很多辦法。而且,Windows
系統和linux
系統安裝同樣的簡單粗暴:
Windows:
下載連結:Git最新版本下載官網
(你沒看錯,這個官網網站名字就叫“Git下載Downloading Git
”)
從上面這個連結你可以從官網上下載到最新的Git
軟體
Linux:
開啟shell介面,輸入:
sudo apt-get install git-core
(Git
和Linux
都是同一個作者,所以其實在Linux
系統上安裝反而最簡單方便)
具體圖文安裝教程如下(我知道,有的人的確需要帶路黨才不會出錯,我做的就是這樣的事情):
連結:Windows下的git安裝教程(其實除了選一下安裝目錄,也就是一直下一步)
連結:linux下安裝git(其實就是一句執行命令的事情)
備註:上面linux
系統安裝這個連結,是基於Centos linux
系統環境下,也就是RedHat Enterprise Linux (RHEL)
和Fedora
系列通用的教程。其實常用的linux發行版
一般都會內建好Git
,Ubuntu
系統應該只會更簡單,比如去“應用商店”
找一下……
4.0 這時候(或者某個時候……),Android studio
會自動提示(右下角彈出一個小提示框),你似乎可以繫結下Git
?!
連結:AndroidStudio怎樣和Git關聯
事實上一般Android studio
會很智慧的讓你把提示點開,然後填入Git
安裝目錄地址,找到Git.exe
,確認,就搞定了。然後就會出現方便的Git
控制:
5.0 好吧,原始出奇跡,你可以在cmd中輸入git --version
可以看到,確確實實是裝好了。
然後桌面也會出現Git Bash
圖示(快捷方式),點開它:
6.0 新手學習階段,先學會一個語句:
find . -name ".git" | xargs rm -Rf
這樣當你玩脫了的時候,這個命令可以幫助你刪掉某個專案中Git
的一切(相當於解除安裝該專案的Git
),你可以重新給專案安裝Git
,再來一次……
7.0 Git使用前,需要做一件事。
- 給自己弄個身份,這樣在提交程式碼的時候
Git
可以知道是誰在提交程式碼。命令如下:
git config --global user.name "Tony"
git config --global user.email "Tony@email.com"
(當然你可以叫別的,這只是一個示範案例而已。)
8.0 先把ProviderTest專案的程式碼貼上來:
-
專案檔案目錄
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/add_data"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="新增資料到book"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.20"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.06" />
<Button
android:id="@+id/query_data"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="從book中查詢資料"
app:layout_constraintBottom_toBottomOf="@+id/add_data"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/add_data"
app:layout_constraintTop_toTopOf="@+id/add_data" />
<Button
android:id="@+id/update_data"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:text="更新資料到book"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/add_data"
app:layout_constraintStart_toStartOf="@+id/add_data"
app:layout_constraintTop_toBottomOf="@+id/add_data"
app:layout_constraintVertical_bias="0.06" />
<Button
android:id="@+id/delete_data"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="從book中刪除資料"
app:layout_constraintBottom_toBottomOf="@+id/update_data"
app:layout_constraintEnd_toEndOf="@+id/query_data"
app:layout_constraintStart_toStartOf="@+id/query_data"
app:layout_constraintTop_toTopOf="@+id/update_data" />
</android.support.constraint.ConstraintLayout>
- MainActivity.java
package com.example.providertest;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private String newId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button addData = (Button) findViewById(R.id.add_data);
addData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//新增資料
Uri uri = Uri.parse("content://com.example.databasetest.provider/book");
ContentValues values = new ContentValues();
values.put("name", "王之國度");
values.put("author", "張三");
values.put("pages", 1040);
values.put("price", 55.55);
Uri newUri = getContentResolver().insert(uri, values);
newId = newUri.getPathSegments().get(1);
}
});
Button queryData = (Button) findViewById(R.id.query_data);
queryData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Uri uri = Uri.parse("content://com.example.databasetest.provider/book");
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
if (cursor != null) {
while (cursor.moveToNext()) {
String name = cursor.getString(cursor.getColumnIndex("name"));
String author = cursor.getString(cursor.getColumnIndex("author"));
int pages = cursor.getInt(cursor.getColumnIndex("pages"));
double price = cursor.getDouble(cursor.getColumnIndex("price"));
Toast.makeText(MainActivity.this,
"name is" + name + ",\n author is" + author +
",\n pages is" + pages + ",\n price is" + price,
Toast.LENGTH_SHORT).show();
}
cursor.close();
}
}
});
Button updateData = (Button) findViewById(R.id.update_data);
updateData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//更新資料
Uri uri = Uri.parse("content://com.example.databasetest.provider/book/" + newId);
ContentValues values = new ContentValues();
values.put("name","創世之神");
values.put("pages", 8250);
values.put("price", 198.72);
getContentResolver().update(uri, values, null, null);
}
});
Button deleteData = (Button) findViewById(R.id.delete_data);
deleteData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Uri uri = Uri.parse("content://com.example.databasetest.provider/book/" + newId);
//刪除資料
getContentResolver().delete(uri, null, null);
}
});
}
}
- AndroidManifest.xml沒有修改,就不貼程式碼了。
9.0 具體操作如下(可能知識點講解會相當繁瑣,但我以谷歌
的人品發誓,知識點絕對是不重複的):
- 1.準備工作:
開啟Git Bash
,,進入專案的根目錄下,然後執行git init
這樣準備工作就已經完成了,我們可以繼續Git
之旅。 - 2.提交ProviderTest專案程式碼。
-
在提交之前我們還有一個問題:是不是所有檔案都會加入版本控制當中?
比如說,我們知道Android專案結構
目錄下,build
目錄下的檔案是編譯專案時自動生成的,所以這部分檔案新增到版本控制之中,沒有任何意義,而且還會增加你的資料閱讀量。這裡,
Git
使用的是排除法,它有一套可配性很強的機制,檢查程式碼倉庫目錄下是否存在一個名為.gitignore
的檔案(記事本就可以開啟),它會一行一行去讀取裡面的內容,把每一行指定的檔案
或目錄
排除在版本控制之外(注意:.gitignore
指定的檔案
或目錄
可以使用*
萬用字元)
可以看到,Git
是不管裡面這些檔案的版本控制的。
-
在app模組下還有一個.gitignore
檔案,這個就簡單多了:
由於app模組下基本都是我們自己編寫的程式碼,所以預設只會有其中的
build
目錄不會被新增到版本控制之中。
但我們可以任意新增,比如說app模組
下所有的測試檔案我都只提供給自己用,並不想上傳到Git
版本控制中,那麼我們可以這樣修改app/.gitignore
檔案中的內容:
好,理論講解完畢,提交程式碼只有兩句命令:
先使用add命令將所有檔案新增,命令如下:
git add .
然後執行commit命令完成提交,命令如下:
git commit -m "First commit"
執行結果如下:
我們可以檢視一下提交記錄,命令如下:
git log
執行結果如下:
可以看到,確確實實是提交成功了。
- 3.檢視修改內容
命令如下:
git status
執行結果如下:
可以看到,
Git
提示沒有任何可提交的檔案。
現在我們修改下ProviderTest專案中的程式碼,修改MainActivity.java
中的程式碼:
重新輸入git status
命令,結果如下:
可以看到,
Git
提示我們MainActivity.java
檔案已經發生了改變。檢視更改內容命令:
git diff
命令執行結果如下:
減號代表刪除部分,
加號代表新增部分。
如果只想檢視MainActivity.java
檔案修改的部分:
git dif fapp/src/main/java/com/example/providertest/MainActivity.java
命令執行結果如下:- 4.撤銷未提交的修改
這可以解決我們有時候程式碼寫的過於草率,以至於原本正常的功能,結果反而被我們改出了問題。
遇到這種問題,我們只要程式碼未提交,修改的內容可以通過Git命令
撤銷。
比如撤銷上面價格的修改:
git checkout app/src/main/java/com/example/providertest/MainActivity.java
命令執行結果如下:
我們點開Android Studio,檢視MainActivity.java檔案:
會發現程式碼已被自動還原成價格45.96。
再執行git status
命令檢查一下,結果如下:
可見,撤銷不僅真的撤銷成功了,而且
Git
也認為它已經撤銷成功了。
但是如果某個檔案已經新增了,那麼就無法撤銷其修改的內容,比如我們重新把價格改為55.55,然後執行如下命令:
gti add .
再執行git status
命令檢查一下,結果如下:
如果我們再執行一遍
checkout
命令,會發現Android Studio
裡面ProviderTest
專案中MainActivity.java
檔案的內容無法被撤銷掉:我們可以取消新增,然後撤銷,取消新增命令如下:
git reset HEAD app/src/main/java/com/example/providertest/MainActivity.java
執行結果如下:
檢視
Android Studio
裡面ProviderTest
專案中MainActivity.java
檔案,又回滾到價格45.96。
- 5.檢視提交記錄。
上面已經介紹了,我們繼續把Android Studio
裡面ProviderTest
專案中MainActivity.java
檔案中的價格修改為55.55,然後再執行一次提交操作:
git add .
git commit -m "Change price"
重新執行git log
,執行結果如下:
當提交記錄較多時,如果只想檢視其中一條記錄,我們可以指定該記錄的id,並加上-1
參數列示我們只想看到一行記錄,命令如下:
git log c8405ae68eed5e6d7b20fa9a4c84caf09619fd3c -1
執行結果如下:
如果想看這條記錄修改了什麼內容,可以在命令中加入-p
引數,命令如下:
git log c8405ae68eed5e6d7b20fa9a4c84caf09619fd3c -1 -p
執行結果如下:
就說到這裡。
END
相關文章
- CRM Transaction處理中的許可權控制
- Android許可權處理分類Android
- Android應用程式獲得root許可權Android
- 值得注意的 Android 應用程式許可權–資訊圖Android
- 許可權控制庫 Casbin 在 Slim 中的應用
- .NET 程式許可權控制、獲得管理員許可權程式碼
- 【Git】程式碼許可權&分支管理Git
- 自定義Android應用的訪問許可權Android訪問許可權
- 微信、企微小程式使用taro對位置許可權進行處理
- 類的許可權與應用
- Vue2.0-token許可權處理Vue
- 【故障處理】修改SPFILE無許可權
- Elasticsearch 許可權控制Elasticsearch
- PowerDesigner版本控制器設定許可權
- android - 解決“應用自定義許可權重名”Android
- Android許可權管理之Permission許可權機制及使用Android
- Linux的許可權控制Linux
- Vue 前端應用實現RBAC許可權控制的一種方式Vue前端
- 使用nginx控制ElasticSearch訪問許可權NginxElasticsearch訪問許可權
- 如何用 Vue 實現前端許可權控制(路由許可權 + 檢視許可權 + 請求許可權)Vue前端路由
- Android進階 Android6 0執行時許可權處理Android
- Linux下ACL許可權控制以及用sudo設定使用者對命令的執行許可權Linux
- 許可權處理 - 用redis實現分散式session~ (cookie && session )Redis分散式SessionCookie
- Linux許可權控制Linux
- Appfuse:許可權控制APP
- Android系統許可權和root許可權Android
- MYSQL學習筆記13: DCL許可權控制(使用者許可權操作)MySql筆記
- k8s結合jumpserver做kubectl許可權控制 使用者在多個namespaces的訪問許可權 rbac許可權控制K8SServernamespace訪問許可權
- Microsoft Graph for Office 365 - Azure AD應用程式許可權ROS
- 資料分析的許可權控制
- Solaris下控制ftp的許可權FTP
- Git 分支管理:最佳化版本控制與應急處理的關鍵策略Git
- iOS 10設定應用許可權iOS
- android許可權大全Android
- Android permission許可權Android
- Vue 前端應用進行身份認證許可權控制的一種方法Vue前端
- Laravel實現許可權控制Laravel
- mysql 許可權控制筆記MySql筆記