制作 ubuntu 系统启动 u 盘

下载发行版镜像

有这几个供参考:ubuntu、xbuntu、mate ubuntu

ubuntu

  • Startup Disk Creator(启动盘创建器)
1
2
3
4
# install
sudo apt-get install usb-creator-gtk
# run
usb-creator-gtk

mac

windows

如何找到 Linux 的版本号

1
2
3
uname -srm
# uname --kernel-name --kernel-release --machine
# Linux 4.13.0-46-generic x86_64
1
cat /etc/os-release

Checking Your Ubuntu Version From the Terminal

1
lsb_release -a

How do you run Ubuntu Server with a GUI?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# Minimal GUI:
sudo apt install xorg
sudo apt install --no-install-recommends openbox

# Minimal GUI with display manager:
sudo apt install xorg
sudo apt install --no-install-recommends lightdm-gtk-greeter
sudo apt install --no-install-recommends lightdm
sudo apt install --no-install-recommends openbox

# A more functional minimal desktop environment (the one I use):
sudo apt install xorg
sudo apt install --no-install-recommends lightdm-gtk-greeter
sudo apt install --no-install-recommends lightdm
sudo apt install --no-install-recommends lxde-icon-theme
sudo apt install --no-install-recommends lxde-core
sudo apt install --no-install-recommends lxde-common
sudo apt install --no-install-recommends policykit-1 lxpolkit
sudo apt install --no-install-recommends lxsession-logout
sudo apt install --no-install-recommends gvfs-backends

# A full lightweight desktop environment:
sudo apt install xorg
sudo apt install --no-install-recommends xubuntu-core
# or
sudo apt install --no-install-recommends ubuntu-mate-core

Can I access Ubuntu from Windows remotely?

https://www.tweaking4all.com/software/linux-software/use-xrdp-remote-access-ubuntu-14-04/

vmware esxi

目标

~ 自动化
~ 规模化
~ 低成本
~ 高效率

理论学科

1
2
3
4
5
6
> https://time.geekbang.org/column/article/8701
> 理论学科。你需要学习像算法、数据结构、网络模型、计算机原理等计算机科学专业需要学习的知识。为什么要学好这些理论上的知识呢?
> 其一,这些理论知识可以说是计算机科学这门学科最精华的知识了。说得大一点,这些是人类智慧的精华。你只要想成为高手,这些东西是你必需要掌握和学习的。
> 其二,当你在解决一些很复杂或是很难的问题时,这些基础理论知识可以帮到你很多。我过去这 20 年从这些基础理论知识中受益匪浅。
> 其三,这些理论知识的思维方式可以让你有触类旁通,一通百通的感觉。虽然知识比较难啃,但啃过以后,你将获益终生。
> ———— 陈浩

become a better developer




How To Ask Questions The Smart Way

If you want to improve your self-confidence, improve your skills

https://medium.com/darius-foroux/i-have-15-ideas-to-change-your-life-do-you-have-5-minutes-f84c3f99b3c5
If you don’t believe in yourself, don’t try to search for it in motivational posts, talks, or books.

You only improve your self-confidence by becoming good at something. How do you get good? By learning, doing, seeing results, and repeating that process for years. Your confidence will grow slowly every day.

How To Build The Self-Confidence You Need To Win At Life

1
2
3
4
5
- Improve your competencies
- Put them into practice
- See results
- Grow more confident
- Repeat

The Most Important Skill Nobody Taught You – Personal Growth – Medium

1
2
3
4
5
6
7
8
9
10
11
12
Fortunately, there is a solution. The only way to avoid being ruined by this fear — like any fear — is to face it. It’s to let the boredom take you where it wants so you can deal with whatever it is that is really going on with your sense of self. That’s when you’ll hear yourself think, and that’s when you’ll learn to engage the parts of you that are masked by distraction.

The beauty of this is that, once you cross that initial barrier, you realize that being alone isn’t so bad. Boredom can provide its own stimulation.

...

The oldest philosophical wisdom in the world has one piece of advice for us:
know yourself. And there is a good reason why that is.

Without knowing ourselves, it’s almost impossible to find a healthy way to interact with the world around us.
Without taking time to figure it out, we don’t have a foundation to built the rest of our lives on.

使用for in 循环Object会有个问题,会loop来自prototype的属性,使用的时候要小心;

1
2
3
4
5
6
7
8
9
10
11
12
13
for (var key in validation_messages) {
// skip loop if the property is from prototype
if (!validation_messages.hasOwnProperty(key)) continue;

var obj = validation_messages[key];
for (var prop in obj) {
// skip loop if the property is from prototype
if(!obj.hasOwnProperty(prop)) continue;

// your code
alert(prop + " = " + obj[prop]);
}
}

或者:

1
2
3
4
5
6
7
8
9
10
11
12
13
14

var obj = {
first: "John",
last: "Doe"
};

//
// Visit non-inherited enumerable keys
//
Object.keys(obj).forEach(function(key) {

console.log(key, obj[key]);

});

参考资料

https://stackoverflow.com/questions/921789/how-to-loop-through-a-plain-javascript-object-with-the-objects-as-members

集成依赖

1
2
3
4
5
6
7
8
9
allprojects {
repositories {
mavenCentral();
jcenter()
maven {
url "http://repo.baichuan-android.taobao.com/content/groups/BaichuanRepositories/"
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 //!+Baichuan

//fastjson
compile 'com.alibaba:fastjson:1.2.9'

//支付
compile 'com.alibaba.alipay:alipaySingle:20160825@jar'

//登陆
compile 'com.ali.auth.sdk:alibabauth_core:1.1.4@jar'
compile 'com.ali.auth.sdk:alibabauth_ui:1.1.4@aar'
compile 'com.ali.auth.sdk:alibabauth_ext:1.1.4@jar'

//【可选】仅供特殊合作伙伴使用

//compile 'com.ali.auth.sdk:alibabauth_accountlink:1.1.4@jar'

//安全基础
compile 'com.taobao.android:securityguardaar3:5.1.81@aar'

//【可选】安全高级,如使用了发放红包、优惠券高级功能,则必须引入

//compile 'com.taobao.android:securitybodyaar3:5.1.25@aar'

//Mtop网关
compile 'com.taobao.android:mtopsdk_allinone_open:1.2.2.4@jar'

//applink
compile 'com.taobao.android:alibc_applink:2.0.0.9@jar'

//UT
compile 'com.taobao.android:utdid4all:1.1.5.3_proguard@jar'
compile 'com.alibaba.mtl:app-monitor-sdk:2.5.1.3_for_bc_proguard@jar'

//电商SDK
compile 'com.alibaba.sdk.android:alibc_trade_sdk:3.1.1.11@aar'

//!-Baichuan

工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
//: Baichuan.java
public class Baichuan {

public static void showDetailPage(Activity activity, String id, String pid, CallbackContext callbackContext) {
AlibcBasePage alibcBasePage = new AlibcDetailPage(id);
AlibcTaokeParams alibcTaokeParams = new AlibcTaokeParams(pid, "", "");
if (!alibcTaokeParams.isValidPid()) {
callbackContext.error("pid无效");
return;
}
showPage(activity, alibcBasePage, alibcTaokeParams, callbackContext);
}

public static void showDetailPageWithUrl(Activity activity, String url, CallbackContext callbackContext) {
AlibcBasePage alibcBasePage = new AlibcPage(url);
showPage(activity, alibcBasePage, null, callbackContext);
}


private static void showPage(Activity activity, AlibcBasePage alibcBasePage, AlibcTaokeParams alibcTaokeParams, final CallbackContext callbackContext) {

AlibcShowParams alibcShowParams = new AlibcShowParams(OpenType.Native, false);

HashMap<String, String> exParams = new HashMap<>();
exParams.put(AlibcConstants.ISV_CODE, "appisvcode");

AlibcTrade.show(activity, alibcBasePage, alibcShowParams, alibcTaokeParams, exParams, new AlibcTradeCallback() {

@Override
public void onFailure(int i, String s) {
callbackContext.error("导航失败:" + s);
}

@Override
public void onTradeSuccess(TradeResult tradeResult) {
switch (tradeResult.resultType) {
case TYPEPAY:
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("successArr", tradeResult.payResult.paySuccessOrders);
jsonObject.put("failureArr", tradeResult.payResult.payFailedOrders);
callbackContext.success(jsonObject);
} catch (JSONException e) {
e.printStackTrace();
callbackContext.error("json转换异常:" + e.getMessage());
}
break;
case TYPECART:
callbackContext.success("您已经将商品添加到购物车了,赶快去购买吧");
break;
default:
callbackContext.error("未知的结果类型");
break;
}
}
});
}

public static void login(final Activity context) {

final AlibcLogin alibcLogin = AlibcLogin.getInstance();

alibcLogin.showLogin(context, new AlibcLoginCallback() {

@Override
public void onSuccess() {
Toast.makeText(context, "登录成功 ", Toast.LENGTH_LONG).show();
//获取淘宝用户信息
Log.i("Baichuan", "获取淘宝用户信息: " + AlibcLogin.getInstance().getSession());

}

@Override
public void onFailure(int code, String msg) {
Toast.makeText(context, "登录失败 ", Toast.LENGTH_LONG).show();
}
});
}
}

cordova调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
名称: MyPlugin.toDetailPage
描述: 跳转到淘宝商品详情页面
参数:
JSONParam —— pid和isCounpons必传,goodsId和couponsUrl对应isCounpons选其一
{
pid: 'mm_131641132_33126906_320380416', // 用户对应pid,此参数必传!!!
isCoupons: 0, // 是否有优惠券,传0(无)或者1(有)
goodsId: '550548242323', // 商品id
couponsUrl: '优惠券地址' // 优惠券地址
}
onSuccess —— 成功时的回调,如用户进行购买,则返回{"successArr":paySuccessOrders, "failureArr":payFailedOrders},Dictionary类型;如用户将商品加入购物车,则返回“您已经将商品添加到购物车了,赶快去购买吧”,String类型
onError —— 失败时的回调,返回失败原因,String类型
使用方法:
MyPlugin.toDetailPage({goodsId: '550548242323', pid: 'mm_131641136_43126906_310380416', isCoupons: 0}, function (success){},function (error){})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
private boolean toDetailPage(CordovaArgs args, CallbackContext callbackContext) {
try {
JSONObject params = args.getJSONObject(0);

if (params.has("isCoupons") && params.getInt("isCoupons") == 1) {
String couponsUrl = params.has("couponsUrl") ? params.getString("couponsUrl") : "";
Baichuan.showDetailPageWithUrl(mContext, couponsUrl, callbackContext);
return true;
}

String pid = params.has("pid") ? params.getString("pid") : "";
if (TextUtils.isEmpty(pid)) {
callbackContext.error("获取PID参数失败");
return true;
}

// use goodsId and pid
String id = params.has("goodsId") ? params.getString("goodsId") : "";
Baichuan.showDetailPage(mContext, id, pid, callbackContext);

} catch (JSONException e) {
e.printStackTrace();
callbackContext.error("获取参数失败:" + e.getMessage());
}
return true;
}

install

个人觉得难点在于:密码、授权、密钥的配置。这一步走通了,后面的就好走了。

config

remove

/var/log/jenkins/jenkins.log

CI & CD

.gitlab-ci.yml

Runner

  • Install GitLab Runner using the official GitLab repositories | GitLab

    1
    2
    3
    4
    curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash

    apt-cache madison gitlab-runner
    sudo apt-get install gitlab-runner=10.8.0
  • Registering Runners | GitLab

    1
    2
    3
    4
    5
    6
    7
    8
    9
    sudo gitlab-runner register \
    --non-interactive \
    --url "http://gitlab.lyloou.com/" \
    --registration-token "xxxxxxxxxxxxx" \
    --executor "shell" \
    --description "shell-runner" \
    --tag-list "shell" \
    --run-untagged="true" \
    --locked="false"

-【GITLAB】 服务配置可持续集成部署的项目案例 - 安装篇 - 个人文章 - SegmentFault 思否

1
2
3
4
sudo gitlab-runner list
gitlab-runner unregister --url http://gitlab.example.com/ --token t0k3n
gitlab-runner unregister --name test-runner
gitlab-runner unregister --all-runners

!!#ff0000

Runner的大版本号要和gitlab的在版本号保持一致。
如:Runner 10.8.0 ~ gitlab 10.2.4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
//: MainActivity.java
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(BuildConfig.TEST_ENV);
}
mWvContent = (WebView) findViewById(R.id.wv_content);
mWvContent.setScrollbarFadingEnabled(true);
mWvContent.addJavascriptInterface(new JavaScriptInterface(mWvContent), "android");
WebSettings settings = mWvContent.getSettings();
settings.setJavaScriptEnabled(true);
settings.setBuiltInZoomControls(true);
settings.setDisplayZoomControls(false);
settings.setDatabaseEnabled(true);
settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
settings.setDomStorageEnabled(true);
settings.setAllowFileAccess(true);
settings.setAppCacheEnabled(true);
settings.setAppCachePath(mWvContent.getContext().getCacheDir().getAbsolutePath());
settings.setJavaScriptCanOpenWindowsAutomatically(true);
settings.setBlockNetworkImage(false);

mWvContent.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
}
});
mWvContent.setWebChromeClient(new WebChromeClient() {

@Override
public void onReceivedTitle(WebView view, String title) {
super.onReceivedTitle(view, title);
TextView tvTitle = toolbar.findViewById(R.id.tv_top_title);
tvTitle.setTextColor(Color.WHITE);
tvTitle.setText(title);
}

@Override
public void onProgressChanged(WebView view, int newProgress) {
super.onProgressChanged(view, newProgress);
if (!isScrolled && newProgress > 50) {
int lastPosition = Usp.getInstance().getInt(sKey + "position", 0);
view.scrollTo(0, lastPosition);
isScrolled = true;
}
}

@Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
boolean b = super.onConsoleMessage(consoleMessage);
System.out.println("|");
System.out.println("============console==========");
System.out.println(consoleMessage.message());
System.out.println("===========console===========");
return b;

}
});

mWvContent.loadUrl(mUrl);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//: JavaScriptInterface.java
// https://blog.csdn.net/FDoubleman/article/details/78189332
public class JavaScriptInterface {
private Context mContext;
private WebView mWebView;

JavaScriptInterface(WebView webView) {
mContext = webView.getContext();
mWebView = webView;
}

@JavascriptInterface
public String showToast(String str) {
final IWXAPI api = WXApiModule.getInstans().getWXApi();
Toast.makeText(mContext, str, Toast.LENGTH_LONG).show();
//WebActivity.newInstance(mContext, "https://m3.renrenyoupin.com", "tag");
return Uresult.newInstance().status(0).msg(String.valueOf(api.isWXAppInstalled())).toMap().toString();
}

@JavascriptInterface
public void executeJs(String str) {
mWebView.post(() -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
mWebView.evaluateJavascript(str, value -> {
System.out.println(value);
});
} else {
mWebView.loadUrl(str);
}
});
}
}

(Plugin version) VS (Required Gradle version)

Android Gradle plugin release notes | Android Developers

了解在构建生命周期的各个阶段所花费的时间

通过 --profile 来生成报告

1
./gradlew assembleDebug --profile

android studio error- mixing versions can lead to run-time crashes

1
2
3
4
5
6
7
8
9
10
11
// Add these lines of code in your build.gradle (Module:app) file at end:
configurations.all {
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
def requested = details.requested
if (requested.group == 'com.android.support') {
if (!requested.name.startsWith("multidex")) {
details.useVersion '27.1.1'
}
}
}
}

<<<<<<< HEAD

proxy

java -DsocksProxyHost=10.1.1.2 -DsocksProxyPort=8877 -Djava.net.socks.username=alibaba -Djava.net.socks.password=secret

AndroidStudio 彻底关闭 http 网络代理方法 - Mr.Liu - CSDN 博客

AndroidStudio 中 Gradle 的 Socks 代理设置 - WittyCollegeStudent 的博客 - CSDN 博客

Android Studio 代理配置指南 · 奔跑的锅炉

Android Gradle 下载的依赖包位置

Android Gradle 下载的依赖包位置 - 简书

Mac 系统默认下载到:/Users/(用户名)/.gradle/caches/modules-2/files-2.1

Windows 系统默认下载到:C:\Users(用户名).gradle\caches\modules-2\files-2.1

举个例子:
错误如下: Download Failed :https://jcenter.bintray.com/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.2.31/kotlin-compiler-embeddable-1.2.31.jar
文件夹生成的规律是根据依赖中的组织名称,classpath”org.jetbrains.kotlin:kotlin-gradle-plugin
地址路径则查找位置是:
C:\Users\Administrator.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-compiler-embeddable\1.2.71\b394ac31590bff78aea6619b8dc0e2c0958aa599

还有一种方式:使用 everything 软件来搜索关键字,找到对应目录;

多渠道打包

1
2
3
4
5
6
7
8
9
10
android {
productFlavors {
flavorA {
// ...
}
flavorB {
// ...
}
}
}

and then imported into build.gradle:

1
2
3
4
5
6
apply plugin: 'com.android.application'
apply from: './build_flavors.gradle'

android {
// the rest of your android configuration
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
android {
...
//flavorDimensions is mandatory with flavors. Use the same name on your 2 files to avoid other conflicts.
flavorDimensions "dim"
productFlavors {
nocustomer{
dimension "dim"

// App and library's flavor have the same name.
// MatchingFallbacks can be omitted
matchingFallbacks = ["nocustomer"]
}
customerNb{
dimension "dim"

// Here the app and library's flavor are different
// Matching fallbacks will select the library's flavor 'customer001'
matchingFallbacks = ["customer001"]
}
}
...
}
dependencies {
implementation project(':zblelib')
}
  • 《Gradle 权威指南》 dimension

多个 dimension 的前后关系是有优先级顺序的,越靠前的优先级越高:

查找冲突的版本号技巧

1
2
./gradlew lib1:dependencies | grep -C 3 com.android.support:appcompat-v7:27.1.1
./gradlew app:dependencies | grep -C 3 com.android.support:appcompat-v7:27.1.1

通过上面的方式,可以看到哪个依赖使用了不同的版本号,接着就可以排除方法:

1
2
3
4
5
implementation ("org.kie.modules:com-google-code-gson:6.5.0.Final"){
exclude group: 'com.google.code.gson', module: 'gson'
}
// 使用自己版本的,其中在 gradle.properties中声明 GSON_VERSION=2.8.5
implementation "com.google.code.gson:gson:$GSON_VERSION"

75ce2b45ad080aeaf919f35ffb1afa47ad0b6cac

0%