谷歌的云存储服务将再次发动价格战,从亚马逊用户手中抢夺100PB的空间

2015 年 7 月 23 日 Google 面向全球市场推出云端存储服务 Cloud Storage Nearline,该服务的特别是快速存取、价格低廉,为吸引更多其他竞争对手的用户使用 Google Cloud Storage Nearline,Google将向企业用户免费赠送100PB 存储空间。

2015 年 3 月 Google 启动云储存服务Cloud Storage Nearline 的测试工作,该服务以快速存取为特点,这一服务在 2015 年 7 月 23 日正式上线,Cloud Storage Nearline 的收费标准是 1GB 每月费用为 1 美分。

为推广 Cloud Storage Nearline 服务,特别是吸引其他竞争对手(主要是 Amazon Web Services)的用户加入 Google 的云储存平台,用户从任何一家云端服务商转移到 Google Cloud Storage Nearline,均可以免费获赠 100PB 存储空间,同时 Google 还推出了云端资料迁移服务,帮助用户更顺利地过渡到 Google 的平台上。

Google 推出低廉的云端存储服务,意在与 Amazon 云服务竞争,云端存储市场价格战不可避免,当云存储服务价格越来越低,消费者可选的服务商越来越多,这一市场很难有利可图。

长期观察中国市场生态,了解中国本地多项产业的变化与市场知识,提供第一手的中国市场观察。 现居中国上海,同时也关注全球的资讯软件、电子商务、互联网与移动运算设备的持续发展。

Latest posts by linli (see all)

微信扫描二维码或者搜索微信公众号(TechNews科技新报)关注我们。

  • 回响 留下回响
  • 发布日期 2015 年 07 月 24 日 10:02
  • 分类 云计算
  • 分享

苹果IOS 14系统,你可以忽略这六个提示,真的很实用

分享最实在的玩机技巧,洞察最前沿的科技资讯!大家好,这里是手机科技园!

相信很多人都将手中iPhone,升级到了iOS 14版本,对比上一个版本,在功能和使用感受上,都有了很大提升。

当然也有很多朋友用的是老机型,不敢乱升级。我给的建议是,iPhone X以上机型还是值得升级的,毕竟iOS 15也快来了,再不升就没机会了。

今天就带大家盘点一下,苹果iOS 14系统中,可能被你忽视的6个小技巧,真的很实用。

01*轻敲背面截屏

iOS 14系统加入了一个黑科技功能,打开「设置」-「辅助功能」-「触控」-「轻点背面」,将轻点两下设置为截屏。当我们需要截屏,用手指在背面敲两下,即可快速截屏。

这个功能刚出来的时候,很多果粉发现很容易误触,比如:将手机放在桌子上就会触发截屏。不过后来经过几次系统更新,误触问题得到了解决!

02*智能叠放小组件

iOS 14以前的小组件都在负一屏,升级后,可以将小组件添加到主屏幕了。先长按主屏幕,桌面图标开始抖动后,点击左上角的「+」,添加小组件到桌面。

系统自带大部分应用,提供2×2、2×4、4×4三种比例,我更喜欢用智能叠放小组件,可以滑动进行切换,看上去更加高级。

03*视频画中画

iPhone终于支持弹窗功能了,打开「设置」-「同样」-「画中画」,开启后面的按钮。以后我们可以一边看视频、一边聊微信。

这个「画中画」小窗口,支持在优酷、爱奇艺、B站上使用,可以在桌面任意位置拖动,也可以直接将它隐藏在侧边栏,视频不会中断哦。

04*语音备忘录优化

苹果手机自带的语音备忘录,就是一台录音机,你可以选择「编辑录音」,然后点击左上角的魔术棒,它可以消除录音环境中的噪音、杂音。

我通过会在开会的时候全程录音,事后再打开录音转文字助手,选择导入外部音频,然后从手机本地找到音频文件,点击就能转写,实测非常有效!

05*前置摄像头镜像

iPhone自拍非常丑,明明屏幕中显示的照镜子,拍下后左右就颠倒了;在iOS 14系统中,相机设置里新增了一个「镜像前置镜头」选项,点击将它开启。

当我们自拍后,打开照片查看,画面和屏幕中看到的一模一样。

如果自拍的时候忘记开启了镜像,其实也可以手动翻转照片的,编辑照片选择裁剪,左上角就有翻转按钮。

06*更改默认浏览器

最后这个功能我也是等待了很久,因为平时用谷歌浏览器较多,之前是没办法更改默认的Safari浏览器,不过iOS 14终于支持更改默认浏览器了,可以通过第三方浏览器设定。

今天这个苹果iOS 14系统,可能被你忽视的6个小技巧,现在大家都知道了吧,觉得不错的话可以分享出去,这样能够帮助到更多的人。

谷歌推出了Chrome操作系统附近的共享文件

作为苹果 AirDrop 文件分享功能的一个竞争对手,谷歌已在近期的 Play 服务测试版中引入了 Nearby Share 。尽管仍处于功能开发的早期阶段,还是有一些线索表明,谷歌或将该功能引入 PC、Mac、Linux、甚至 Chrome OS 平台。虽然尚不清楚 Nearby Share 将于何时登陆前三大桌面平台,但 XDA-Developers 爆料称,我们已经可以在 Chrome OS 上体验这项功能。

该功能的工作原理很是简洁明了:首先用户必须启用 Nearby Share 标记,然后在“设置 -> 已连接设备”中看到附近分享的选项,这样就算准备就绪了。

此时只需选择想要向附近设备发送的文件,然后在服务列表中选择 Nearby Share,即可将文件发送到同样启用了该功能的其它设备上,但对方仍会看到一个是否接收文件分享的弹窗。

目前 Nearby Share 文件分享功能已可在部分 Android 智能机上使用,并且运行状况良好。感兴趣的朋友可以尝试通过 Play 服务测试版开启这项体验,或者直接从 APKMirror 镜像站点下载 Play Services beta 的 APK 安装包。

研究干货——如何免费获得英国文学?

本文主要分享如何查找英文文献,全文干货,建议先收藏再阅读!

比较常用的查找英文文献的网站有:

NCBI的PubMed(加载巨慢)Web of Science(要用校园网)谷歌学术

附上实操方法:用谷歌学术查找文献

1.查找文献

(1)首先,打开谷歌学术镜像网址;

谷歌学术镜像_Google镜像站scholar.hedasudi.com

(2)以话题“新型冠状病毒2019-nCoV“为对象,进行文献搜索,搜索结果如下:

(3)接下来,点击我们感兴趣的搜索结果,进入文章页面,复制文章的DOI或者URL。

2.解锁文献

要知道,并不是所有文献都是免费开放的,遇到需要收费的文献,就需要大招:SCI-HUB

就让小科给大家示范一下具体步骤吧:

(1)首先打开SCI-HUB网页;

sci-hub文献检索gfsoso.99lb.net

(2)将复制的DOI或者URL粘贴到SCI-HUB中,点击搜索;

(3)输入验证码即可下载文献的PDF格式。

3.整理文献

之前的回答:有哪些好用的文献工具 里分享过整理文献的软件,开篇就是EndNote这个整理文献神器。所以,我们今天就用EndNote对文献进行整理分类

具体步骤如下所示:

1.(登陆Science Direct) 对Search results进行筛选

(检索的消息可以是你已知的文章名称、作者、关键词、文章编号等等)

点击搜索后出现以下界面

(假设选定这篇“分离了一种新型的豆科溶菌酶并研究抗真菌活性”时,通过Abstract和Keywords还想做进一步了解,由于需要付费,可将文章标题复制粘贴到“SCI-HUB”,进行免费阅读下载。)

2.(登陆SCI-HUB)

输入文章标题后,即可免费在线阅读,并且免费下载PDF

版权申明:本文来源网络,版权归原作者所有。

文章转摘只为学术传播,如涉及侵权问题,请联系我们,我们将及时修改或删除。

无法下载外语文档。那是因为你的下载方法是错误的

版权声明

来源(首发):微信公众号《技能Tools》

今天为大家介绍一下小编个人在下载外文文献时的方法及工具,仅供大家参考。

百度学术

https://xueshu.baidu.com

当需要下载外文文献时,首先想到的是百度学术。在搜索栏输入关键词或论文题目即可看到相关的论文及其来源(包括全网免费下载源),你可以按照来源提示点击进入相关的网站进行文献的免费下载。(有时有些最新文献是不能免费下载的)。

谷歌学术

https://scholar.Google.com

与百度学术文献搜索下载方式大同小异。谷歌上搜索到的文献基本上都跟随有文献的下载链接。

不能上谷歌学术网操作的小伙伴使用下面的谷歌学术镜像网站进行搜索。

谷歌学术镜像网站

https://ac.scmor.com

Sci-Hub

https://sci-hub.tw

Sci-Hub是一个可以下载任意谷歌上有电子版链接文献与杂志的网站,只要输入想要下载的文献的DOI号就可以获取到该文献的真实地址并在线浏览和下载,被称为“科学界的海盗湾”。一篇论文只有一个DOI号,从它被期刊录用就有了,相当于文章的身份证,相当靠谱

该网站的网址由于某种原因经常变换(你懂得),有时需要自己在网络上查找最新网址,不过很容易找到的。实在找不到时你也可以参考下面这个网站

https://gfsoso.99lb.net/sci-hub.html

所以当你在百度学术或谷歌学术上下载不到想要的外文文献时,你就注意一下该文献介绍页上的DOI号了,DOI号全部以10.开头,这时候该Sci-Hub上场了。下面以百度学术上文献互助上的一篇文献为例给大家演示一下Sci-Hub的使用。

如果出现无线输入验证码的情况,建议把你的电脑换个网络试一下。

Sci-Bay

https://sci-bay.org

这里给大家推荐一个集合了谷歌学术和Sci-Hub功能的网站——Sci-Bay,这个网站的搜索界面和结果都套用了 Google 的学术搜索,但在每一条结果后面都附有 Sci-Hub 的全文链接,让你更加方便的的使用下载。

如果你有更好的下载的方式,欢迎关注留言交流。

谷歌推出Linux仅暂停交换空间,以改善SSD的使用寿命和安全性

在 Google 工程师和很多开发者的共同努力下,他们希望在 Linux 系统中创建新的 swap 空间,这些 swap 空间将只保留给系统挂起/休眠使用,而不是常规的交换到磁盘。

在名为“SWAP_FLAG_HIBERNATE_ONLY”的提案中,开发者希望保留一个 swap 空间,只用于 suspend-to-disk 使用而不需要常规的“页”(pages,磁盘分割成固定大小的区块)交换。到目前为止,如果只是想在系统挂起时使用通用交换,最终需要启用通用交换,没有办法在挂起过程中打开/关闭它。

在关于该提案的描述如下:

有几个原因使 usermode 可能希望能够专门引导 swap 空间和休眠。一个原因是与 SSD的磨损有关。休眠的耐力和速度要求与交换不同。例如,将 hibernate 保留在主存储中,而将 swap 放在 SLC 命名空间中可能是有利的。这些命名空间的速度更快,耐力更好,但在容量上要花费3-4倍。独家引导休眠和交换使系统设计者能够准确地划分他们的存储,而不会耗尽他们的主存储,或过度配置他们的快速交换区。

另一个允许独家转向的原因是与安全有关的。设计具有抵御离线攻击能力的系统的要求在交换和休眠之间是不同的。由于页面可以被任意添加和删除,交换实际上需要一个哈希值的字典,而休眠只需要整个镜像的一个哈希值。如果你为交换设置了块级的完整性,为休眠设置了图像级的完整性,那么允许交换块可能泄露到休眠区域是有问题的,因为它创建的交换页不受任何完整性保护。

安卓工作室北极狐(2020.3.1)稳定版正式发布

作者 / Amanda Alexander, Android 产品经理

我们高兴地宣布,Android Studio Arctic Fox 现已正式进入稳定版发布渠道,欢迎大家下载。这个最新版本支持 Jetpack Compose 1.0,用于构建原生界面的 Android 全新工具包。另外,此版本也强调对多设备类型的覆盖,包括 Wear OS 设备,并提供新版后台任务管理器等功能,帮助开发者提高工作效率。我们基于开发者的反馈打造出了这套全新的 Android Studio,助力开发者社区更快地构建高质量、现代化的应用,且覆盖多样的设备!

请注意: 去年,我们 宣布 调整 Android Studio 的版本编号方案,以匹配 Android Studio 所基于的 IntelliJ IDEA 的年份和版本,并加入我们自己的补丁程序编号。我们将使用代号 (按字母顺序递增): 第一个是 Arctic Fox,第二个是 Bumblebee (目前处于 Canary 版)。Android Studio Arctic Fox (2020.3.1) 将 Android Studio 更新到了 IntelliJ 平台的 2020.3 版本,其中加入了大量新功能,包括调试程序交互提示、VCS 更新以及几项新的代码编辑器改进,以提升您的工作效率。请阅读 IntelliJ 的 版本说明 了解详情。

为让大家快速设计现代化 UI,我们针对 Jetpack Compose 添加了额外的功能。借助 Compose Preview,您可以为 Compose UI 的多个组件创建预览,以便在多个维度 (如主题、屏幕和字号大小等) 即时查看您的修改带来的变化。部署预览 (Deploy Preview) 至设备的功能让您可以直接将 Compose 代码片段部署到设备或模拟器中,以便快速测试一小段代码。我们在布局检查器 (Layout Inspector) 中添加了 Compose 支持,方便您在需要更深入了解布局时,能够轻松地理解布局的渲染方式。此外,我们还新增了字元实时编辑功能,这样您就可以在预览中以及在模拟器或实体设备运行应用时,即时查看 Compose 代码的变化结果,而无需再次进行编译。

在强化设备支持方面,我们构建了新的 Wear OS 配对助手,以简化 Wear OS 模拟器与实体或虚拟手机的配对。您还可以立即通过 Wear OS 3 的开发者预览版系统映像来使用最新版本的 Wear OS。当您运行 Wear OS 模拟器时,您还会发现我们增加了对心率传感器 (Heart Rate Sensor) API 的支持。我们针对面向 Google TV 的应用加入了最新的 Google TV 遥控器功能,并更新了 Google TV 系统映像,让大家可以体验最新的界面设计。此外,我们完善了 Automotive OS 的开发和测试工作流,让开发者可以使用模拟器回放汽车传感器数据来模拟驾驶场景。对于面向平板电脑的应用,我们更新了所有的模板,使它们原生支持横屏。无论您是针对小屏还是大屏设备进行开发,我们都加入了新的功能来帮助您持续打造创新且出色的应用。

最后,为提高开发者的工作效率,我们增加了一些能让您更高效工作的功能。例如,我们为 Android 12 添加了 lint 检查,从而帮助大家构建面向下一代 Android 的应用。为帮助您测试代码,我们在布局编辑器 (Layout Editor) 中增加了无障碍功能扫描器 (Accessibility Scanner),以便您更轻松地识别布局中的无障碍问题,而新的测试矩阵 (Test Matrix) 让您可以实时跨多设备并行查看测试结果。此外,我们添加了对搭载 Apple 芯片 (arm64) 的硬件的预览支持,并扩展了模拟器控件,以扩大测试的覆盖面。最后,在调试方面,新的后台任务检查器 (Background Task Inspector) 可以帮助您分析应用的后台任务处理器 (worker)。

Android Studio Arctic Fox 中的改进不胜枚举。要查看完整更新列表,请参阅 Android Studio Arctic Fox (2020.3.1) Beta 版发布文章 和 版本说明。您也可以观看下面的视频了解不容错过的更新亮点。 您也可以观看 视频 了解不容错过的更新亮点。

△ Android Studio Arctic Fox 不容错过的更新亮点

设计

使用 @Preview 注释生成 Compose 代码的预览,并对多个组件的不同配置 (例如不同设备或主题) 进行可视化。Compose Preview 可以让您更轻松地针对代码中的 Composables 创建心理映射。

△ Compose Preview

Layout Inspector 支持 Compose

无论应用是完全通过 Compose 打造,还是结合使用了 Compose 和 Views,Layout Inspector 都能让您获取更多有关布局的详情,并进行问题排查。例如,您能够看到传递至各个 Composable 的参数和修饰符。在开发应用时,您还可以选择启用实时更新 (Live Updates),以从设备串流数据。

△ Compose Layout Inspector

字元实时编辑

您现在可以快速编辑代码中的字元 (字符串、数字、布尔运算等),并立即在屏幕 (不论是预览、模拟器或实体设备) 上查看更改结果,而无需进行编译。

△ 字元实时编辑: 编辑字符串,并在预览中实时查看改动结果

设备

Wear OS 配对

全新 Wear OS 配对助手将帮助您完成配对,从而简化 Wear OS 模拟器与虚拟或实体手机的配对过程。请注意,此功能目前可用于和 Wear OS 2 配套设备的配对,对 Wear OS 3 的支持将在不久后推出。请阅读 官方文档 了解详情。

△ Wear OS 模拟器配对助手对话框

△ 手机 + 手表模拟器配对成功状态

开发者生产力

后台任务检查器 (Background Task Inspector)

当在运行级别 26 或更高级别 API 的设备上使用 WorkManager 库 2.5.0 或更高版本时,您可以使用全新的后台任务检查器 (Background Task Inspector) 来可视化、监控和调试应用的后台任务处理器。从菜单栏依次选择 View (视图) > Tool Windows (工具窗口) > App Inspection (应用检查),即可访问此工具。请阅读 官方文档 了解详情。

下面简要总结一下 Android Studio Arctic Fox (2020.3.1) 稳定版新增的优化和功能:

设计

  • Compose Preview
  • 后台任务检查器 (Background Task Inspector)
  • 部署预览到设备
  • 字元实时编辑

设备

  • Wear OS 配对
  • 心率传感器
  • 新版 Wear OS 系统映像
  • Google TV 遥控
  • Google TV 系统映像
  • Automotive OS 传感器回放
  • 平板电脑模板支持

开发者生产力

  • IntelliJ 2020.3.1
  • Android 12 lint 检查
  • 非传递性 R 类重构
  • Apple 芯片支持预览
  • Android 模拟器扩展控件
  • 后台任务检查器 (Background Task Inspector)
  • 布局编辑器中的无障碍功能扫描器 (Accessibility Scanner)
  • 测试矩阵 (Test Matrix)
  • 内存分析器 (Memory Profiler) 的新录制界面
  • AGP 升级助手改进
  • C++ 编辑器: 在调试程序中设置执行点

欲了解更多详细信息,请参阅 Android Studio 版本说明、Android Gradle 插件版本说明 以及 Android 模拟器版本说明。

即刻开始使用

下载 Android Studio

您现在就可以 下载最新版本 的 Android Studio Arctic Fox,或者 下载 Apple 芯片预览版。如果您使用的是之前版本的 Android Studio,则只需更新到最新版本的 Android Studio 即可。如果您想保留稳定版本的 Android Studio,则可以同时运行 Android Studio Arctic Fox 稳定版和 Canary 版本。请阅读 官方文档 了解详情。

我们期待着您的反馈,无论是您喜欢的内容、产品中的问题,以及希望加入的功能。如果您发现错误或问题,欢迎随时 提交 给我们。

Android反向基金会

0x01 activity 跳转

demo还是上一次的demo,这次我们更改一下Button逻辑,改成跳转。

建一个新的Activity

跳转Activity

这里跳转到我们新建的Activity。

使用intent进行跳转,Intent相当于一个载体。

具体代码如下:

Intent i=new Intent(MainActivity.this,Main2Activity.class);
startActivity(i);

设置标识

生成apk测试

0x02 Androidmanifest.xml说明

首先来看下Androidmanifest.xml的内容

<?xml version=”1.0″ encoding=”utf-8″?>
<manifest xmlns:android=”https://schemas.android.com/apk/res/android”
package=”com.example.hanlei.first_demo”>
<application
android:allowBackup=”true”
android:icon=”@mipmap/ic_launcher”
android:label=”@string/app_name”
android:supportsRtl=”true”
android:theme=”@style/AppTheme”>
<activity android:name=”.MainActivity”>
<intent-filter>
<action android:name=”android.intent.action.MAIN” />
<category android:name=”android.intent.category.LAUNCHER” />
</intent-filter>
</activity>
<activity android:name=”.Main2Activity”></activity>
</application>
</manifest>

在这里我们可以看到有两个Activity。

如何设置最先启动?

这里有两个Activity,那么app是怎么识别那个是最先启动的Activity呢。

这里我们对比一下两个Activity的区别。

这是第一个Activity

<activity android:name=”.MainActivity”>
<intent-filter>
<action android:name=”android.intent.action.MAIN” />
<category android:name=”android.intent.category.LAUNCHER” />
</intent-filter>
</activity>

这个是我们的第二个Activity

<activity android:name=”.Main2Activity”></activity>

是不是区别很明显,一个有一大堆的内容,一个只有一句话。

所以我们的重点就是:

<intent-filter>
<action android:name=”android.intent.action.MAIN” />
<category android:name=”android.intent.category.LAUNCHER” />
</intent-filter>

很容易就发现是因为这个所以才是最先启动的。

我们来做一个简单的测试。

我们把这个移动一下位置。

现在Androidmanifest,xml是这个样子。

<?xml version=”1.0″ encoding=”utf-8″?>
<manifest xmlns:android=”https://schemas.android.com/apk/res/android”
package=”com.example.hanlei.first_demo”>
<application
android:allowBackup=”true”
android:icon=”@mipmap/ic_launcher”
android:label=”@string/app_name”
android:supportsRtl=”true”
android:theme=”@style/AppTheme”>
<activity android:name=”.MainActivity”>
</activity>
<activity android:name=”.Main2Activity”>
<intent-filter>
<action android:name=”android.intent.action.MAIN” />
<category android:name=”android.intent.category.LAUNCHER” />
</intent-filter>
</activity>
</application>
</manifest>

测试

现在我们生成apk。

我们发现,点开之后发现已经不是之前的Activity,而是我们之后自己添加的Activity。

基于这个思路,我们可以想嘛,如果有第三方的Activity注入,我们是不是可以通过改变启动的Activity从而避开一些验证问题。

恩,之后通过实战来进行一个测试。

0x03 反编译

有到了学习smali的时候到了。可能很无聊吧,但是写的人却是很有兴趣呢。

废话不说,开始吧。

1. 丢Android Killer里。

2.找到关键代码

恩。在$2里。

.method public onClick(Landroid/view/View;)V
.locals 3
.param p1, “v” # Landroid/view/View;
.prologue
.line 33
new-instance v0, Landroid/content/Intent;
iget-object v1, p0, Lcom/example/hanlei/first_demo/MainActivity$2;->this$0:Lcom/example/hanlei/first_demo/MainActivity;
const-class v2, Lcom/example/hanlei/first_demo/Main2Activity;
invoke-direct {v0, v1, v2}, Landroid/content/Intent;-><init>(Landroid/content/Context;Ljava/lang/Class;)V
.line 34
.local v0, “i”:Landroid/content/Intent;
iget-object v1, p0, Lcom/example/hanlei/first_demo/MainActivity$2;->this$0:Lcom/example/hanlei/first_demo/MainActivity;
invoke-virtual {v1, v0}, Lcom/example/hanlei/first_demo/MainActivity;->startActivity(Landroid/content/Intent;)V
.line 35
return-void
.end method

这里我们不一句一句翻译,想看的回去翻之前的内容,很多。

我们来看这里的主要代码:

新建一个 Intent对象

new-instance v0, Landroid/content/Intent;

获取MainActivity对想存储在v1中

iget-object v1, p0, Lcom/example/hanlei/first_demo/MainActivity$2;->this$0:Lcom/example/hanlei/first_demo/MainActivity;

把Main2Activity存入v2中

const-class v2, Lcom/example/hanlei/first_demo/Main2Activity;

然后把v1和v2放入v0中。

invoke-direct {v0, v1, v2}, Landroid/content/Intent;-><init>(Landroid/content/Context;Ljava/lang/Class;)V

startActivity调用即可。还是很简单的,很容易理解的。

.line 34
.local v0, “i”:Landroid/content/Intent;
iget-object v1, p0, Lcom/example/hanlei/first_demo/MainActivity$2;->this$0:Lcom/example/hanlei/first_demo/MainActivity;
invoke-virtual {v1, v0}, Lcom/example/hanlei/first_demo/MainActivity;->startActivity(Landroid/content/Intent;)V

怎么说呢,smali见过了,虽然不知道什么意思,但是很熟悉,一下子就理解了。恩,语言还是多看看,多分析分析,有好处的。当初学c语言的时候就是,敲了很多行,做了几个项目恩就很熟练了。

0x04 实战分析

样本

样本为了方便我就传在百度云里了

原APK:链接:https://pan.baidu.com/s/1pMwcuef 密码:a673

试玩

不知道为什么我的夜深模拟器打不开了。试试别的模拟器。

一打开游戏,就弹出个这个界面,很不喜欢,我想直接弹出我的游戏界面。

好,我们用我们刚开始的技能。

1.apk反编译

2.查看Androidmanifest.xml文件

<?xml version=”1.0″ encoding=”utf-8″ standalone=”no”?>
<manifest xmlns:android=”https://schemas.android.com/apk/res/android” android:installLocation=”preferExternal” package=”com.sxiaoao.farm.farmherohx”>
<uses-feature android:glEsVersion=”0x00020000″ android:required=”true”/>
<uses-permission android:name=”android.permission.WAKE_LOCK”/>
<uses-permission android:name=”android.permission.INTERNET”/>
<uses-permission android:name=”android.permission.VIBRATE”/>
<uses-permission android:name=”android.permission.ACCESS_NETWORK_STATE”/>
<uses-permission android:name=”android.permission.READ_PHONE_STATE”/>
<uses-permission android:name=”android.permission.WRITE_SETTINGS”/>
<uses-permission android:name=”android.permission.WRITE_EXTERNAL_STORAGE”/>
<uses-permission android:name=””/>
<uses-permission android:name=”android.permission.MOUNT_UNMOUNT_FILESYSTEMS”/>
<uses-permission android:name=”android.permission.ACCESS_WIFI_STATE”/>
<uses-permission android:name=”android.permission.GET_TASKS”/>
<uses-permission android:name=”android.permission.DISABLE_KEYGUARD”/>
<uses-permission android:name=”android.permission.READ_CONTACTS”/>
<uses-permission android:name=”android.permission.SYSTEM_ALERT_WINDOW”/>
<uses-permission android:name=”android.permission.ACCESS_FINE_LOCATION”/>
<uses-permission android:name=”com.android.launcher.permission.INSTALL_SHORTCUT”/>
<uses-permission android:name=”com.android.launcher.permission.UNINSTALL_SHORTCUT”/>
<uses-permission android:name=”com.android.launcher.permission.READ_SETTINGS”/>
<uses-permission android:name=”com.android.launcher.permission.WRITE_SETTINGS”/>
<uses-permission android:name=”android.permission.INTERNET”/>
<uses-permission android:name=”android.permission.ACCESS_WIFI_STATE”/>
<uses-permission android:name=”com.google.android.providers.gsf.permission.READ_GSERVICES”/>
<uses-permission android:name=”android.permission.ACCESS_NETWORK_STATE”/>
<uses-permission android:name=”android.permission.ACCESS_WIFI_STATE”/>
<application android:icon=”@drawable/icon” android:label=”美人鱼消消” android:name=”com.sxiaoao.farm.farmherohx.CmgameApplication”>
<activity android:configChanges=”keyboard|keyboardHidden|orientation|screenSize” android:label=”美人鱼消消” android:launchMode=”singleTask” android:name=”MainActivity” android:screenOrientation=”sensorPortrait”/>
<activity android:configChanges=”keyboard|keyboardHidden|orientation|screenSize” android:label=”美人鱼消消” android:launchMode=”singleTask” android:name=”LogActivity” android:screenOrientation=”sensorPortrait”/>
<activity android:configChanges=”keyboard|orientation|screenSize” android:name=”cn.cmgame.billing.api.GameOpenActivity” android:screenOrientation=”sensorPortrait” android:theme=”@android:style/Theme.NoTitleBar.Fullscreen”>
<intent-filter>
<action android:name=”android.intent.action.MAIN”/>
<category android:name=”android.intent.category.LAUNCHER”/>
<category android:name=”tv.ouya.intent.category.GAME”/>
</intent-filter>
<intent-filter>
<action android:name=”android.intent.action.CHINAMOBILE_OMS_GAME”/>
<category android:name=”android.intent.category.CHINAMOBILE_GAMES”/>
</intent-filter>
</activity>
<activity android:name=”cn.cmgame2_0.launch_model.shortcut.main.MiguHomeActivity” android:screenOrientation=”portrait” android:theme=”@android:style/Theme.Dialog”>
<intent-filter>
<action android:name=”android.intent.action.MAIN”/>
<category android:name=”cn.cmgame2_0.category.migu_home”/>
</intent-filter>
</activity>
<service android:name=”cn.cmgame.billing.service.GameService”/>
<activity android:configChanges=”keyboard|keyboardHidden|orientation|screenSize” android:exported=”true” android:label=”美人鱼消消” android:launchMode=”singleTop” android:name=”com.sxiaoao.farm.farmherohx.wxapi.WXEntryActivity” android:screenOrientation=”sensorPortrait”/>
<receiver android:name=”com.xiaoao.pay.util.update.UpdataBroadcastReceiver”>
<intent-filter>
<action android:name=”android.intent.action.DOWNLOAD_COMPLETE”/>
</intent-filter>
</receiver>
<meta-data android:name=”UMENG_APPKEY” android:value=”552f4eeafd98c57677001cb8″/>
<meta-data android:name=”UMENG_CHANNEL” android:value=”8556″/>
</application>
</manifest>

3.尝试跳转

首先来看下我们的跳转。

<activity android:configChanges=”keyboard|orientation|screenSize” android:name=”cn.cmgame.billing.api.GameOpenActivity” android:screenOrientation=”sensorPortrait” android:theme=”@android:style/Theme.NoTitleBar.Fullscreen”>
<intent-filter>
<action android:name=”android.intent.action.MAIN”/>
<category android:name=”android.intent.category.LAUNCHER”/>
<category android:name=”tv.ouya.intent.category.GAME”/>
</intent-filter>
<intent-filter>
<action android:name=”android.intent.action.CHINAMOBILE_OMS_GAME”/>
<category android:name=”android.intent.category.CHINAMOBILE_GAMES”/>
</intent-filter>
</activity>

跳转的Activity名称为:cn.cmgame.billing.api.GameOpenActivity,Gameopen。。。恩,这是什么唉,好奇怪。但是呢,肯定就是我们打开的界面。恩。我觉得这个有点重要,以后可能会涉及到。所以还是找个小本子记下来。我应该建立一个小本子。

我们来看一下我们的Activity。

<activity android:configChanges=”keyboard|keyboardHidden|orientation|screenSize” android:label=”美人鱼消消” android:launchMode=”singleTask” android:name=”MainActivity” android:screenOrientation=”sensorPortrait”/>
<activity android:configChanges=”keyboard|keyboardHidden|orientation|screenSize” android:label=”美人鱼消消” android:launchMode=”singleTask” android:name=”LogActivity” android:screenOrientation=”sensorPortrait”/>

这里有两个Activity:

第一个Activity的name:android:name=”MainActivity”

第二个Activity的name:android:name=”LogActivity”

作为开发人员,MainActivity,就是一个开始恩。我们直接开始更改。

<activity android:configChanges=”keyboard|keyboardHidden|orientation|screenSize” android:label=”美人鱼消消” android:launchMode=”singleTask” android:name=”MainActivity” android:screenOrientation=”sensorPortrait”>
<intent-filter>
<action android:name=”android.intent.action.MAIN”/>
<category android:name=”android.intent.category.LAUNCHER”/>
<category android:name=”tv.ouya.intent.category.GAME”/>
</intent-filter>
<intent-filter>
<action android:name=”android.intent.action.CHINAMOBILE_OMS_GAME”/>
<category android:name=”android.intent.category.CHINAMOBILE_GAMES”/>
</intent-filter>
</activity>

这个是修改后的Activity。

其实我也只是对

<action android:name=”android.intent.action.MAIN”/>
<category android:name=”android.intent.category.LAUNCHER”/>

这两句有了解。但是还有三句是什么,一起来看一下吧。关于测试的问题,我们学习完之后再进行测试吧。

首选是

<category android:name=”tv.ouya.intent.category.GAME”/>

国内百度搜不到。

收藏的谷歌镜像掉链子。

bing或许是一个不错的选择。

这个是我找到的结果。

Cortex,ARM公司在经典处理器ARM11以后的产品改用Cortex命名,并分成A、R和M三类,旨在为各种不同的市场提供服务。

For your Cortex app to show up in the PLAY section,这句话的含义就是,在你的ARM app 展现的游戏部分。我用百度翻译+自己瞎编的也不知道对不对哈。

it must have an activity that contains a filter for either。它必须有一个包含过滤器的活动。

说这么多废话。我又不做游戏开发。说不定以后要做,但是现在不做。所以说白了,就是必须的。

其实我之前做了一个错误的测试就是直接把

<action android:name=”android.intent.action.MAIN”/>
<category android:name=”android.intent.category.LAUNCHER”/>

这两个直接挪过去,直接失败。所以,还是分析一下吧。

刚才说的

<category android:name=”tv.ouya.intent.category.GAME”/>

这句就是必须的。

还有两句

<action android:name=”android.intent.action.CHINAMOBILE_OMS_GAME”/>
<category android:name=”android.intent.category.CHINAMOBILE_GAMES”/>

好了,我们搜一搜,最后发现是:移动基地运营商sdk需要添加所必须的。

好嘛,做测试的时候直接挪过来的。现在我们删了做一下测试吧。

4.测试

测试结果,成功了。不过值得一说的是蓝叠模拟器也掉链子了。还是自己的手机好用啊。成功的跳过了。手机发图好麻烦的,恩,自己做测试吧。

以上。

将docker图像大小减少90%的三个技巧|优化和调整

概述

在构建Docker容器时,应该尽量想办法获得体积更小的镜像,因为传输和部署体积较小的镜像速度更快。

但RUN语句总是会创建一个新层,而且在生成镜像之前还需要使用很多中间文件,在这种情况下,该如何获得体积更小的镜像呢?

你可能已经注意到了,大多数Dockerfiles都使用了一些奇怪的技巧:

FROM ubuntu
RUN apt-get update && apt-get install vim

为什么使用&&?而不是使用两个RUN语句代替呢?比如:

FROM ubuntu
RUN apt-get update
RUN apt-get install vim

从Docker 1.10开始,COPY、ADD和RUN语句会向镜像中添加新层。前面的示例创建了两个层而不是一个。

镜像的层就像Git的提交(commit)一样。

Docker的层用于保存镜像的上一版本和当前版本之间的差异。就像Git的提交一样,如果你与其他存储库或镜像共享它们,就会很方便。

实际上,当你向注册表请求镜像时,只是下载你尚未拥有的层。这是一种非常高效地共享镜像的方式。

但额外的层并不是没有代价的。

层仍然会占用空间,你拥有的层越多,最终的镜像就越大。Git存储库在这方面也是类似的,存储库的大小随着层数的增加而增加,因为Git必须保存提交之间的所有变更。

过去,将多个RUN语句组合在一行命令中或许是一种很好的做法,就像上面的第一个例子那样,但在现在看来,这样做并不妥。


1. 通过Docker多阶段构建将多个层压缩为一个

当Git存储库变大时,你可以选择将历史提交记录压缩为单个提交。

事实证明,在Docker中也可以使用多阶段构建达到类似的目的。

在这个示例中,你将构建一个Node.js容器。

从index.js开始:

const express = require(‘express’)
const app = express()
app.get(‘/’, (req, res) => res.send(‘Hello World!’))
app.listen(3000, () => {
console.log(`Example app listening on port 3000!`)
})

和package.json:

{
“name”: “hello-world”,
“version”: “1.0.0”,
“main”: “index.js”,
“dependencies”: {
“express”: “^4.16.2”
},
“scripts”: {
“start”: “node index.js”
}
}

你可以使用下面的Dockerfile来打包这个应用程序:

FROM node:8
EXPOSE 3000
WORKDIR /app
COPY package.json index.js ./
RUN npm install
CMD [“npm”, “start”]

然后开始构建镜像:

$ docker build -t node-vanilla .

然后用以下方法验证它是否可以正常运行:

$ docker run -p 3000:3000 -ti –rm –init node-vanilla

你应该能访问https://localhost:3000,并收到“Hello World!”。

Dockerfile中使用了一个COPY语句和一个RUN语句,所以按照预期,新镜像应该比基础镜像多出至少两个层:

$ docker history node-vanilla
IMAGE CREATED BY SIZE
075d229d3f48 /bin/sh -c #(nop) CMD [“npm” “start”] 0B
bc8c3cc813ae /bin/sh -c npm install 2.91MB
bac31afb6f42 /bin/sh -c #(nop) COPY multi:3071ddd474429e1… 364B
500a9fbef90e /bin/sh -c #(nop) WORKDIR /app 0B
78b28027dfbf /bin/sh -c #(nop) EXPOSE 3000 0B
b87c2ad8344d /bin/sh -c #(nop) CMD [“node”] 0B
<missing> /bin/sh -c set -ex && for key in 6A010… 4.17MB
<missing> /bin/sh -c #(nop) ENV YARN_VERSION=1.3.2 0B
<missing> /bin/sh -c ARCH= && dpkgArch=”$(dpkg –print… 56.9MB
<missing> /bin/sh -c #(nop) ENV NODE_VERSION=8.9.4 0B
<missing> /bin/sh -c set -ex && for key in 94AE3… 129kB
<missing> /bin/sh -c groupadd –gid 1000 node && use… 335kB
<missing> /bin/sh -c set -ex; apt-get update; apt-ge… 324MB
<missing> /bin/sh -c apt-get update && apt-get install… 123MB
<missing> /bin/sh -c set -ex; if ! command -v gpg > /… 0B
<missing> /bin/sh -c apt-get update && apt-get install… 44.6MB
<missing> /bin/sh -c #(nop) CMD [“bash”] 0B
<missing> /bin/sh -c #(nop) ADD file:1dd78a123212328bd… 123MB

但实际上,生成的镜像多了五个新层:每一个层对应Dockerfile里的一个语句。

现在,让我们来试试Docker的多阶段构建。

你可以继续使用与上面相同的Dockerfile,只是现在要调用两次:

FROM node:8 as build
WORKDIR /app
COPY package.json index.js ./
RUN npm install
FROM node:8
COPY –from=build /app /
EXPOSE 3000
CMD [“index.js”]

Dockerfile的第一部分创建了三个层,然后这些层被合并并复制到第二个阶段。在第二阶段,镜像顶部又添加了额外的两个层,所以总共是三个层。

现在来验证一下。首先,构建容器:

$ docker build -t node-multi-stage .

查看镜像的历史:

$ docker history node-multi-stage
IMAGE CREATED BY SIZE
331b81a245b1 /bin/sh -c #(nop) CMD [“index.js”] 0B
bdfc932314af /bin/sh -c #(nop) EXPOSE 3000 0B
f8992f6c62a6 /bin/sh -c #(nop) COPY dir:e2b57dff89be62f77… 1.62MB
b87c2ad8344d /bin/sh -c #(nop) CMD [“node”] 0B
<missing> /bin/sh -c set -ex && for key in 6A010… 4.17MB
<missing> /bin/sh -c #(nop) ENV YARN_VERSION=1.3.2 0B
<missing> /bin/sh -c ARCH= && dpkgArch=”$(dpkg –print… 56.9MB
<missing> /bin/sh -c #(nop) ENV NODE_VERSION=8.9.4 0B
<missing> /bin/sh -c set -ex && for key in 94AE3… 129kB
<missing> /bin/sh -c groupadd –gid 1000 node && use… 335kB
<missing> /bin/sh -c set -ex; apt-get update; apt-ge… 324MB
<missing> /bin/sh -c apt-get update && apt-get install… 123MB
<missing> /bin/sh -c set -ex; if ! command -v gpg > /… 0B
<missing> /bin/sh -c apt-get update && apt-get install… 44.6MB
<missing> /bin/sh -c #(nop) CMD [“bash”] 0B
<missing> /bin/sh -c #(nop) ADD file:1dd78a123212328bd… 123MB

文件大小是否已发生改变?

$ docker images | grep node-
node-multi-stage 331b81a245b1 678MB
node-vanilla 075d229d3f48 679MB

最后一个镜像(node-multi-stage)更小一些。

你已经将镜像的体积减小了,即使它已经是一个很小的应用程序。

但整个镜像仍然很大!

有什么办法可以让它变得更小吗?


2. 用distroless去除容器中所有不必要的东西

这个镜像包含了Node.js以及yarn、npm、bash和其他的二进制文件。因为它也是基于Ubuntu的,所以你等于拥有了一个完整的操作系统,其中包括所有的小型二进制文件和实用程序。

但在运行容器时是不需要这些东西的,你需要的只是Node.js。

Docker容器应该只包含一个进程以及用于运行这个进程所需的最少的文件,你不需要整个操作系统。

实际上,你可以删除Node.js之外的所有内容。

但要怎么做?

所幸的是,谷歌为我们提供了distroless。

以下是distroless存储库的描述:

“distroless”镜像只包含应用程序及其运行时依赖项,不包含程序包管理器、shell以及在标准Linux发行版中可以找到的任何其他程序。

这正是你所需要的!

你可以对Dockerfile进行调整,以利用新的基础镜像,如下所示:

FROM node:8 as build
WORKDIR /app
COPY package.json index.js ./
RUN npm install
FROM gcr.io/distroless/nodejs
COPY –from=build /app /
EXPOSE 3000
CMD [“index.js”]

你可以像往常一样编译镜像:

$ docker build -t node-distroless .

这个镜像应该能正常运行。要验证它,可以像这样运行容器:

$ docker run -p 3000:3000 -ti –rm –init node-distroless

现在可以访问https://localhost:3000页面。

不包含其他额外二进制文件的镜像是不是小多了?

$ docker images | grep node-distroless
node-distroless 7b4db3b7f1e5 76.7MB

只有76.7MB!

比之前的镜像小了600MB!

但在使用distroless时有一些事项需要注意。

当容器在运行时,如果你想要检查它,可以使用以下命令attach到正在运行的容器上:

$ docker exec -ti <insert_docker_id> bash

attach到正在运行的容器并运行bash命令就像是建立了一个SSH会话一样。

但distroless版本是原始操作系统的精简版,没有了额外的二进制文件,所以容器里没有shell!

在没有shell的情况下,如何attach到正在运行的容器呢?

答案是,你做不到。这既是个坏消息,也是个好消息。

之所以说是坏消息,因为你只能在容器中执行二进制文件。你可以运行的唯一的二进制文件是Node.js:

$ docker exec -ti <insert_docker_id> node

说它是个好消息,是因为如果攻击者利用你的应用程序获得对容器的访问权限将无法像访问shell那样造成太多破坏。换句话说,更少的二进制文件意味着更小的体积和更高的安全性,不过这是以痛苦的调试为代价的。

或许你不应在生产环境中attach和调试容器,而应该使用日志和监控。

但如果你确实需要调试,又想保持小体积该怎么办?


3. 小体积的Alpine基础镜像

你可以使用Alpine基础镜像替换distroless基础镜像。

Alpine Linux是:

一个基于musl libc和busybox的面向安全的轻量级Linux发行版。

换句话说,它是一个体积更小也更安全的Linux发行版。

不过你不应该理所当然地认为他们声称的就一定是事实,让我们来看看它的镜像是否更小。

先修改Dockerfile,让它使用node:8-alpine:

FROM node:8 as build
WORKDIR /app
COPY package.json index.js ./
RUN npm install
FROM node:8-alpine
COPY –from=build /app /
EXPOSE 3000
CMD [“npm”, “start”]

使用下面的命令构建镜像:

$ docker build -t node-alpine .

现在可以检查一下镜像大小:

$ docker images | grep node-alpine
node-alpine aa1f85f8e724 69.7MB
69.7MB!

甚至比distrless镜像还小!

现在可以attach到正在运行的容器吗?让我们来试试。

让我们先启动容器:

$ docker run -p 3000:3000 -ti –rm –init node-alpine
Example app listening on port 3000!

你可以使用以下命令attach到运行中的容器:

$ docker exec -ti 9d8e97e307d7 bash
OCI runtime exec failed: exec failed: container_linux.go:296: starting container process caused “exec: “bash”: executable file not found in $PATH”: unknown

看来不行,但或许可以使用shell?

$ docker exec -ti 9d8e97e307d7 sh / #

成功了!现在可以attach到正在运行的容器中了。

看起来很有希望,但还有一个问题。

Alpine基础镜像是基于muslc的——C语言的一个替代标准库,而大多数Linux发行版如Ubuntu、Debian和CentOS都是基于glibc的。这两个库应该实现相同的内核接口。

但它们的目的是不一样的:

glibc更常见,速度也更快;

muslc使用较少的空间,并侧重于安全性。

在编译应用程序时,大部分都是针对特定的libc进行编译的。如果你要将它们与另一个libc一起使用,则必须重新编译它们。

换句话说,基于Alpine基础镜像构建容器可能会导致非预期的行为,因为标准C库是不一样的。

你可能会注意到差异,特别是当你处理预编译的二进制文件(如Node.js C++扩展)时。

例如,PhantomJS的预构建包就不能在Alpine上运行。

你应该选择哪个基础镜像?

你应该使用Alpine、distroless还是原始镜像?

如果你是在生产环境中运行容器,并且更关心安全性,那么可能distroless镜像更合适。

添加到Docker镜像的每个二进制文件都会给整个应用程序增加一定的风险。

只在容器中安装一个二进制文件可以降低总体风险。

例如,如果攻击者能够利用运行在distroless上的应用程序的漏洞,他们将无法在容器中使用shell,因为那里根本就没有shell!

请注意,OWASP本身就建议尽量减少攻击表面。

如果你只关心更小的镜像体积,那么可以考虑基于Alpine的镜像。

它们的体积非常小,但代价是兼容性较差。Alpine使用了略微不同的标准C库——muslc。你可能会时不时地遇到一些兼容性问题。

原始基础镜像非常适合用于测试和开发。

它虽然体积很大,但提供了与Ubuntu工作站一样的体验。此外,你还可以访问操作系统的所有二进制文件。

再回顾一下各个镜像的大小:

node:8 681MB
node:8 使用多阶段构建为678MB
gcr.io/distroless/nodejs 76.7MB
node:8-alpine 69.7MB


文章很长,但是很实用,玩docker必会,觉得有用的话帮忙点赞转发哦。

后面会分享更多关于自动化运维(devops)内容,感兴趣的朋友可以关注下~

Fuchsia OS源代码国内图片在线

Fuchsia OS 是 Google 正在开发中的一款全新操作系统,同时也是一个开源操作系统,因为一些原因,国内开发者无法直接访问 Fuchsia 的源代码,最近由 Fuchsia 中文社区提供的 Fuchsia OS 源代码国内镜像上线。

感谢息壤开源镜像站和重庆大学镜像站 weerac 同学的努力,Fuchsia OS 源码国内镜像正式上线了。国内开发者们可以通过 Git 方式获得主 repo 核心代码;以及从镜像站获取完整代码,包括第三方代码,以及单独的 tar 包,Fuchsia 镜像同时提供每日当天打包的源码包,方便正在学习和开发 Fuchsia 的同学,该镜像完全由社区志愿者义务维护,可能无法保证 100%

无故障,如果遇到问题,欢迎以及感谢反馈。

镜像服务

说明:包含完整代码,同时提供单独的 tar 包及每日 Archive

  • 网址:https://mirrors.hexang.com/fuchsia

源码包和虚拟机下载

Fuchsia 中文社区同时提供完整源码包和配置好的虚拟机下载,其中虚拟机的用户名和密码皆为 fuchsia

  • https://mirrors.hexang.org

Git 服务

说明:仅包含主 repo 核心代码,不包括第三方代码

  • 网址:https://hexang.org/mirrors/fuchsia
  • 使用:git clone git@hexang.org:mirrors/fuchsia.git

错误报告

说明:使用过程中如果遇到错误,或者无法正常使用 Git服务、镜像服务,请在下列地址创建 issue ,镜像管理团队会在第一时间处理。

  • 网址:https://hexang.org/mirrors/fuchsia/issues