标签: Android

android 使用命令模拟点击 滑动

adb shell getevent -p

%title插图%num

出现上述截图的就是屏幕触摸输入设备

带上 -l

adb shell getevent -p -l

%title插图%num

%title插图%num

获得event 体系里 宽(0035)和高(0036)

通过adb模拟滑动、按键、点击事件

adb shell input -h

%title插图%num

adb shell input text string 在搜索框中自动输入 string

keyevent 手机的按键操作,如:home键、返回键、菜单键、锁屏等

例如需要点击一下home键

adb shell input keyevent 3 或者 adb shell input keyevent KEYCODE_HOME

tap 是模拟touch屏幕的事件,以下命令就是点击屏幕300,300位置

adb shell input tap 300 300

swipe 是滑动事件,以下命令表示从屏幕300,300 移动到400,400

adb shell input swipe 300 300 400 400

KEYCODE_HOME 所在文件

frameworks/base/core/java/android/view/KeyEvent.java

sendevent 命令

sendevent /dev/input/eventX type code value

type、code、value 定义在kernel-3.18/include/uapi/linux/input.h

/*

* Event types
*/

#define EV_SYN 0x00
#define EV_KEY 0x01 –按键
#define EV_REL 0x02 –触摸相对坐标
#define EV_ABS 0x03 –触摸*对坐标
#define EV_MSC 0x04
#define EV_SW 0x05
#define EV_LED 0x11
#define EV_SND 0x12
#define EV_REP 0x14
#define EV_FF 0x15
#define EV_PWR 0x16
#define EV_FF_STATUS 0x17
#define EV_MAX 0x1f
#define EV_CNT (EV_MAX+1)

一般常用的是EV_KEY, EV_REL, EV_ABS, EV_SYN

分别对应keyboard, 相对坐标, *对坐标, 同步事件

EV_SYN对应的code如下

/*
* Synchronization events.
*/

#define SYN_REPORT 0
#define SYN_CONFIG 1
#define SYN_MT_REPORT 2
#define SYN_DROPPED 3
#define SYN_MAX 0xf
#define SYN_CNT (SYN_MAX+1)

input keyevent

模拟按键,sendevent用起来比较繁琐,可以用input keyevent代替

input keyevent 3 // Home (KeyEvent.java)

input keyevent 4 // Back

input keyevent 19 //Up

用senevent 模拟触屏事件

sendevent /dev/input/event1 0003 0000 0000015e // ABS x 坐标

sendevent /dev/input/event1: 0003 0001 000000df // ABS y 坐标

sendevent /dev/input/event1: 0001 014a 00000001 // BTN touch事件 值为1

adb shell input keyevent 82 这个命令会发送一个解屏事件到锁屏的设备上解屏

http://blog.shvetsov.com/2013/02/grab-android-screenshot-to-computer-via.html

adb shell screencap -p | perl -pe ‘s/\x0D\x0A/\x0A/g’ > screen.png 截屏并通过perl输出到本地目录

————————————————

Android实现滑动的四种方式

效果展示

%title插图%num
做Android自定义View开发,实现布局的滑动是必不可少的一项手艺。下面我为大家准备了五种移动布局的方法:

layout 法 CoordinatorLayout原理的简析
LayoutParams 法 CoordinatorLayout原理的简析
scrollTo/scrollBy
Scroller 类
ViewDragHelper 类 : ViewDragHelper 类
activity_main.xml布局文件

<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout 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”
android:orientation=”vertical”
tools:context=”.MainActivity”>

<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width=”match_parent”
android:layout_height=”match_parent”>

<com.wust.SelfCoordinator.CanDragView
android:layout_width=”100dp”
android:layout_height=”100dp”
android:background=”#f00″/>
<TextView
android:layout_width=”100dp”
android:layout_height=”100dp”
android:background=”#0f0″
android:layout_marginTop=”200dp”/>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

</LinearLayout>
这里面存在 CoordinatorLayout 这个布局,是因为我准备写 CoordinatorLayout 布局的教程的,Android滑动方式只是个小插曲,所以,布局文件可以不用按照我的写,仅供参考。

1、layout 法

自定义View的 java 代码

package com.wust.SelfCoordinator;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.Nullable;

/**
* ClassName: CanDragView <br/>
* Description: <br/>
* date: 2021/6/29 9:45<br/>
*
* @author yiqi<br />
* @QQ 1820762465
*/
public class CanDragView extends View {

int startX;
int startY;

public CanDragView(Context context) {
this(context,null);
}

public CanDragView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}

public CanDragView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
{
startX =(int) event.getX();
startY =(int) event.getY();
}
break;
case MotionEvent.ACTION_MOVE:
{
int endX = (int) event.getX();
int endY = (int) event.getY();
int moveX = endX – startX;
int moveY = endY – startY;
System.out.println(“moveX ->” + moveX + “moveY ->” + moveY);
//移动布局的关键性代码
layout(getLeft()+moveX,getTop()+moveY,getRight()+moveX,getBottom()+moveY);
}
break;
}
return true;
}

}
2、LayoutParams 法

package com.wust.SelfCoordinator;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;

import androidx.annotation.Nullable;
import androidx.coordinatorlayout.widget.CoordinatorLayout;

/**
* ClassName: CanDragView <br/>
* Description: <br/>
* date: 2021/6/29 9:45<br/>
*
* @author yiqi<br />
* @QQ 1820762465
*/
public class CanDragView extends View {

int startX;
int startY;

public CanDragView(Context context) {
this(context,null);
}

public CanDragView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}

public CanDragView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
{
startX =(int) event.getX();
startY =(int) event.getY();
}
break;
case MotionEvent.ACTION_MOVE:
{
int endX = (int) event.getX();
int endY = (int) event.getY();
int moveX = endX – startX;
int moveY = endY – startY;
System.out.println(“moveX ->” + moveX + “moveY ->” + moveY);
//移动布局的关键性代码,如果布局已经在 xml 文件中存在,你直接用 getLayoutParams() 获取参数信息就可以了,不要在重新 new
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) getLayoutParams();
params.leftMargin = getLeft()+moveX;
params.topMargin = getTop()+moveY;
setLayoutParams(params);
}
break;
}
return true;
}

}
3、scrollTo/scrollBy

package com.wust.SelfCoordinator;

import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.Nullable;
import androidx.coordinatorlayout.widget.CoordinatorLayout;

/**
* ClassName: CanDragView <br/>
* Description: <br/>
* date: 2021/6/29 9:45<br/>
*
* @author yiqi<br />
* @QQ 1820762465
*/
@SuppressLint(“AppCompatCustomView”)
public class CanDragView extends TextView {

int startX;
int startY;

public CanDragView(Context context) {
this(context,null);
}

public CanDragView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}

public CanDragView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
{
startX =(int) event.getX();
startY =(int) event.getY();
}
break;
case MotionEvent.ACTION_MOVE:
{
int endX = (int) event.getX();
int endY = (int) event.getY();
int moveX = endX – startX;
int moveY = endY – startY;
System.out.println(“moveX ->” + moveX + “moveY ->” + moveY);
//移动布局的关键性代码,scrollTo/scrollBy 移动的是 View中的内容 ViewGroup中的子View
scrollTo(-(getLeft()+moveX),-(getTop()+moveY));
invalidate();
}
break;
}
return true;
}

}
需要注意的两点:

这个方法移动的 布局 的内容,不是自己
得加负号,大家自己尝试一下就明白了

%title插图%num
Scroller 类

原理大家可以参考这篇文章 : Scroller与computeScroll处理滑动

package com.wust.SelfCoordinator;

import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.Scroller;
import android.widget.TextView;

import androidx.annotation.Nullable;
import androidx.coordinatorlayout.widget.CoordinatorLayout;

/**
* ClassName: CanDragView <br/>
* Description: <br/>
* date: 2021/6/29 9:45<br/>
*
* @author yiqi<br />
* @QQ 1820762465
*/
@SuppressLint(“AppCompatCustomView”)
public class CanDragView extends TextView {

int startX;
int startY;
private Scroller scroller;
private int moveX;
private int moveY;

public CanDragView(Context context) {
this(context,null);
}

public CanDragView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}

public CanDragView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//*步:创建 scroller 对象
scroller = new Scroller(context);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
{
startX =(int) event.getX();
startY =(int) event.getY();
}
break;
case MotionEvent.ACTION_MOVE:
{
int endX = (int) event.getX();
int endY = (int) event.getY();
moveX = endX – startX;
moveY = endY – startY;
System.out.println(“moveX ->” + moveX + “moveY ->” + moveY);
//移动布局的关键性代码,scrollTo/scrollBy 移动的是 View中的内容 ViewGroup中的子View
//第二步:开始滚动
scroller.startScroll(getLeft(),getTop(), moveX, moveY);
//这个不能少,因为这个会调用 computeScroll()
invalidate();
}
break;
}
return true;
}

@Override
public void computeScroll() {
//第三步:编写 computeScroll,反复矫正
if (scroller.computeScrollOffset()){
scrollTo(getLeft()+moveX,getTop()+moveY);
invalidate();
}
super.computeScroll();
}
}
这个方法也是移动内容,和 scrollTo / scrollBy 一样。

ViewDragHelper 类
————————————————

android获取音量分贝值

android获取音量分贝值

AudioRecordDemo.java

%title插图%num
package com.example.recording;

import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.util.Log;

public class AudioRecordDemo {
private static final String TAG = “AudioRecord”;
static final int SAMPLE_RATE_IN_HZ = 8000;
static final int BUFFER_SIZE = AudioRecord.getMinBufferSize(SAMPLE_RATE_IN_HZ,
AudioFormat.CHANNEL_IN_DEFAULT, AudioFormat.ENCODING_PCM_16BIT);
AudioRecord mAudioRecord;
boolean isGetVoiceRun;
Object mLock;

public AudioRecordDemo() {
mLock = new Object();
}

public void getNoiseLevel() {
if (isGetVoiceRun) {
Log.e(TAG, “还在录着呢”);
return;
}
mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
SAMPLE_RATE_IN_HZ, AudioFormat.CHANNEL_IN_DEFAULT,
AudioFormat.ENCODING_PCM_16BIT, BUFFER_SIZE);
if (mAudioRecord == null) {
Log.e(“sound”, “mAudioRecord初始化失败”);
}
isGetVoiceRun = true;

new Thread(new Runnable() {
@Override
public void run() {
mAudioRecord.startRecording();
short[] buffer = new short[BUFFER_SIZE];
while (isGetVoiceRun) {
//r是实际读取的数据长度,一般而言r会小于buffersize
int r = mAudioRecord.read(buffer, 0, BUFFER_SIZE);
long v = 0;
// 将 buffer 内容取出,进行平方和运算
for (int i = 0; i < buffer.length; i++) {
v += buffer[i] * buffer[i];
}
// 平方和除以数据总长度,得到音量大小。
double mean = v / (double) r;
double volume = 10 * Math.log10(mean);
Log.d(TAG, “分贝值:” + volume);
if(volume>80){
Log.d(TAG, “恭喜您获得一元优惠券”);
}

// 大概一秒十次
synchronized (mLock) {
try {
mLock.wait(100);

} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
mAudioRecord.stop();
mAudioRecord.release();
mAudioRecord = null;
}
}).start();
}
}
MediaRecorderDemo.java

package com.example.recording;

import java.io.File;
import java.io.IOException;

import android.media.MediaRecorder;
import android.os.Handler;
import android.util.Log;

public class MediaRecorderDemo {
private final String TAG = “MediaRecord”;
private MediaRecorder mMediaRecorder;
public static final int MAX_LENGTH = 1000 * 60 * 10;// *大录音时长1000*60*10;
private String filePath;

public MediaRecorderDemo(){
this.filePath = “/dev/null”;
}

public MediaRecorderDemo(File file) {
this.filePath = file.getAbsolutePath();
}

private long startTime;
private long endTime;

/**
* 开始录音 使用amr格式
*
* 录音文件
* @return
*/
public void startRecord() {
// 开始录音
/* ①Initial:实例化MediaRecorder对象 */
if (mMediaRecorder == null)
mMediaRecorder = new MediaRecorder();
try {
/* ②setAudioSource/setVedioSource */
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 设置麦克风
/* ②设置音频文件的编码:AAC/AMR_NB/AMR_MB/Default 声音的(波形)的采样 */
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
/*
* ②设置输出文件的格式:THREE_GPP/MPEG-4/RAW_AMR/Default THREE_GPP(3gp格式
* ,H263视频/ARM音频编码)、MPEG-4、RAW_AMR(只支持音频且音频编码要求为AMR_NB)
*/
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

/* ③准备 */
mMediaRecorder.setOutputFile(filePath);
mMediaRecorder.setMaxDuration(MAX_LENGTH);
mMediaRecorder.prepare();
/* ④开始 */
mMediaRecorder.start();
// AudioRecord audioRecord.
/* 获取开始时间* */
startTime = System.currentTimeMillis();
updateMicStatus();
Log.i(“ACTION_START”, “startTime” + startTime);
} catch (IllegalStateException e) {
Log.i(TAG,
“call startAmr(File mRecAudioFile) failed!”
+ e.getMessage());
} catch (IOException e) {
Log.i(TAG,
“call startAmr(File mRecAudioFile) failed!”
+ e.getMessage());
}
}

/**
* 停止录音
*
*/
public long stopRecord() {
if (mMediaRecorder == null)
return 0L;
endTime = System.currentTimeMillis();
Log.i(“ACTION_END”, “endTime” + endTime);
mMediaRecorder.stop();
mMediaRecorder.reset();
mMediaRecorder.release();
mMediaRecorder = null;
Log.i(“ACTION_LENGTH”, “Time” + (endTime – startTime));
return endTime – startTime;
}

private final Handler mHandler = new Handler();
private Runnable mUpdateMicStatusTimer = new Runnable() {
public void run() {
updateMicStatus();
}
};

/**
* 更新话筒状态
*
*/
private int BASE = 1;
private int SPACE = 100;// 间隔取样时间

private void updateMicStatus() {
if (mMediaRecorder != null) {
double ratio = (double)mMediaRecorder.getMaxAmplitude() /BASE;
double db = 0;// 分贝
if (ratio > 1)
db = 20 * Math.log10(ratio);
Log.d(TAG,”分贝值:”+db);
mHandler.postDelayed(mUpdateMicStatusTimer, SPACE);
}
}
}
MainActivity.java

package com.example.recording;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;

public class MainActivity extends Activity {

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

}

}
activity_main.xml

<RelativeLayout xmlns:android=”http://schemas.android.com/apk/res/android”
xmlns:tools=”http://schemas.android.com/tools”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:paddingBottom=”@dimen/activity_vertical_margin”
android:paddingLeft=”@dimen/activity_horizontal_margin”
android:paddingRight=”@dimen/activity_horizontal_margin”
android:paddingTop=”@dimen/activity_vertical_margin”
tools:context=”.MainActivity” >

<TextView
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:text=”@string/hello_world” />

</RelativeLayout>
*后别忘 了,在AndroidManifest.xml中配置
<uses-permission android:name=”android.permission.RECORD_AUDIO” />
————————————————

Android:Duplicate class inxmlbeans-2.6.0.jar

Android Studio:3.4.1
还是在瞅easyExcel的时候,出现Duplicate class…found in modules xmlbeans-2.6.0.jar (org.apache.xmlbeans:xmlbeans:2.6.0) and xmlbeans-2.6.0.jar (org.apache.xmlbeans:xmlbeans:2.6.0)的问题。

问题

%title插图%num
Duplicate class org.apache.xmlbeans.xml.stream.Location found in modules xmlbeans-2.6.0.jar (org.apache.xmlbeans:xmlbeans:2.6.0) and xmlbeans-2.6.0.jar (org.apache.xmlbeans:xmlbeans:2.6.0)
Duplicate class org.apache.xmlbeans.xml.stream.ReferenceResolver found in modules xmlbeans-2.6.0.jar (org.apache.xmlbeans:xmlbeans:2.6.0) and xmlbeans-2.6.0.jar (org.apache.xmlbeans:xmlbeans:2.6.0)
Duplicate class org.apache.xmlbeans.xml.stream.XMLEvent found in modules xmlbeans-2.6.0.jar (org.apache.xmlbeans:xmlbeans:2.6.0) and xmlbeans-2.6.0.jar (org.apache.xmlbeans:xmlbeans:2.6.0)
Duplicate class org.apache.xmlbeans.xml.stream.XMLInputStream found in modules xmlbeans-2.6.0.jar (org.apache.xmlbeans:xmlbeans:2.6.0) and xmlbeans-2.6.0.jar (org.apache.xmlbeans:xmlbeans:2.6.0)
Duplicate class org.apache.xmlbeans.xml.stream.XMLName found in modules xmlbeans-2.6.0.jar (org.apache.xmlbeans:xmlbeans:2.6.0) and xmlbeans-2.6.0.jar (org.apache.xmlbeans:xmlbeans:2.6.0)
Duplicate class org.apache.xmlbeans.xml.stream.XMLStreamException found in modules xmlbeans-2.6.0.jar (org.apache.xmlbeans:xmlbeans:2.6.0) and xmlbeans-2.6.0.jar (org.apache.xmlbeans:xmlbeans:2.6.0)
Duplicate class org.apache.xmlbeans.xml.stream.utils.NestedThrowable found in modules xmlbeans-2.6.0.jar (org.apache.xmlbeans:xmlbeans:2.6.0) and xmlbeans-2.6.0.jar (org.apache.xmlbeans:xmlbeans:2.6.0)
Duplicate class org.apache.xmlbeans.xml.stream.utils.NestedThrowable$Util found in modules xmlbeans-2.6.0.jar (org.apache.xmlbeans:xmlbeans:2.6.0) and xmlbeans-2.6.0.jar (org.apache.xmlbeans:xmlbeans:2.6.0)

Go to the documentation to learn how to Fix dependency resolution errors.

解决
疑似2.6.0的bug,在module级build.gradle文件的dependencies中增加xmlbeans3.1.0的依赖即可解决

compile group: ‘org.apache.xmlbeans’, name: ‘xmlbeans’, version: ‘2.6.0’

建议在android中增加multiDexEnable设置

multiDexEnable true

如下图:

%title插图%num

————————————————

【Android】Android 6.0 获取危险权限、运行时权限、一次申请多个权限

从Android 6.0开始,如果是危险权限,都需要经过用户授权才能使用,我们在写项目的时候往往需要弹出窗口询问用户是否授权,称为运行时权限。本文章对运行时权限进行简单总结

一、危险权限列表
Android手机有很多权限,分为普通权限和危险权限。普通权限是不涉及用户隐私的(比如说网络权限),开发者只需要在AndroidManifest声明就能随意使用,危险权限是比较重要的权限(比如说读取联系人、短信、位置等),除了要在AndroidManifest中声明,还需要经过用户授权才能使用,大概分为9组24个权限

注意:用户一旦授权了其中一个权限(名),该权限所在的权限组中的其他权限也会同时被授权

%title插图%num

二、申请权限
1、AndroidManifest声明
首先要把需要的权限在AndroidManifest声明,比如说我们申请 通话、读写、位置权限

<uses-permission android:name=”android.permission.WRITE_EXTERNAL_STORAGE”/>
<uses-permission android:name=”android.permission.ACCESS_FINE_LOCATION”/>
<uses-permission android:name=”android.permission.READ_PHONE_STATE”/>

2、layout布局
就放两个button,分别用于申请单个和多个权限

activity_main.xml

<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
xmlns:tools=”http://schemas.android.com/tools”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:orientation=”vertical”
android:gravity=”center”
tools:context=”.MainActivity”>

<Button
android:id=”@+id/btn_single”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:text=”单个权限”/>
<Button
android:id=”@+id/btn_multiple”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:text=”多个权限”/>

</LinearLayout>

3、java代码
MaiActivity.java

public class MainActivity extends AppCompatActivity implements View .OnClickListener{
private Button btn_single,btn_multiple;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

btn_single = findViewById(R.id.btn_single);
btn_single.setOnClickListener(this);
btn_multiple = findViewById(R.id.btn_multiple);
btn_multiple.setOnClickListener(this);
}

@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.btn_single:
requestPermission_single();//申请单个权限
break;
case R.id.btn_multiple:
requestPermission_multiple();//申请多个权限
break;
default:
break;
}
}
private void requestPermission_single(){
……
}
private void requestPermission_multiple(){
……
}

//不管用户是否授权,都会回调这个函数
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
……
}
}

4、申请单个权限
private void requestPermission_single(){
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1);
}else {
Log.e(“11111111”, “requestPermission_single: 已经获得写入权限了”);//处理自己的代码
}
}

 

5、申请多个权限
private void requestPermission_multiple(){
List<String> permissionList = new ArrayList<>();
if (ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED){
permissionList.add(Manifest.permission.ACCESS_FINE_LOCATION);
}
if (ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED){
permissionList.add(Manifest.permission.READ_PHONE_STATE);
}
if (ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
permissionList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (!permissionList.isEmpty()){
String[] permissions = permissionList.toArray(new String[permissionList.size()]);
ActivityCompat.requestPermissions(MainActivity.this,permissions,2);
}else {
Log.e(“222222222”, “requestPermission_multiple: 已经获得所有权限”);//处理自己的代码
}
}

6、处理申请结果
//不管用户是否授权,都会回调这个函数
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode){
case 1:
if (grantResults.length>0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
Log.e(“1111111”, “onRequestPermissionsResult: 申请单个权限授权成功” );//处理自己的代码
}else{
Log.e(“1111111”, “onRequestPermissionsResult: 申请单个权限授权失败” );
}
break;
case 2:
if (grantResults.length>0){
for (int result : grantResults){
if (result != PackageManager.PERMISSION_GRANTED){
Log.e(“2222222222”, “onRequestPermissionsResult: 用户拒*了一个或多个权限”);
return;
}
}
//处理自己的代码
Log.e(“2222222222”, “onRequestPermissionsResult: 用户授权了所有权限”);//处理自己的代码
}else {
Log.e(“2222222222”, “onRequestPermissionsResult: 程序运行错误” );
}
break;
default:
break;
}
}

————————————————

记录Android端使用zbar扫描的相关问题

在此一并做一下记录。

修改Zbar有效扫描区域的关键代码,在CaptureActivity中initCamera函数中

  1. CameraManager.get().openDriver(surfaceHolder);
  2. Point point = CameraManager.get().getCameraResolution();
  3. int width = point.y;
  4. int height = point.x;
  5. int x = mCropLayout.getLeft() * width / mContainer.getWidth();
  6. int y = mCropLayout.getTop() * height / mContainer.getHeight();
  7. int cropWidth = mCropLayout.getWidth() * width / mContainer.getWidth();
  8. int cropHeight = mCropLayout.getHeight() * height / mContainer.getHeight() – (iHeight – height);// 由于扫描框的大小,比实际扫描的高度矮,故减去(iHeight – height)的高度
  9. setX(x);
  10. setY(y);
  11. setCropWidth(cropWidth);
  12. setCropHeight(cropHeight);

解码并保存图片的相关代码,在DecodeHandler中decode函数中

  1. private void decode(byte[] data, int width, int height)
  2. {
  3. byte[] rotatedData = new byte[data.length];
  4. for (int y = 0; y < height; y++)
  5. {
  6. for (int x = 0; x < width; x++)
  7. rotatedData[x * height + height y 1] = data[x + y * width];
  8. }
  9. int tmp = width;// Here we are swapping, thats the difference to #11
  10. width = height;
  11. height = tmp;
  12. ZbarManager manager = new ZbarManager();
  13. String result = manager.decode(rotatedData, width, height, true, activity.getX(), activity.getY(), activity.getCropWidth(), activity.getCropHeight());
  14. if (result != null)
  15. {
  16. if (activity.isNeedCapture())
  17. {
  18. // 生成bitmap
  19. PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(rotatedData, width, height, activity.getX(), activity.getY(), activity.getCropWidth(),
  20. activity.getCropHeight(), false);
  21. int[] pixels = source.renderThumbnail();
  22. int w = source.getThumbnailWidth();
  23. int h = source.getThumbnailHeight();
  24. Bitmap bitmap = Bitmap.createBitmap(pixels, 0, w, w, h, Bitmap.Config.ARGB_8888);
  25. try
  26. {
  27. String rootPath = Environment.getExternalStorageDirectory().getAbsolutePath() + “/Qrcode/”;
  28. File root = new File(rootPath);
  29. if (!root.exists())
  30. {
  31. root.mkdirs();
  32. }
  33. File f = new File(rootPath + “Qrcode.jpg“);
  34. if (f.exists())
  35. {
  36. f.delete();
  37. }
  38. f.createNewFile();
  39. FileOutputStream out = new FileOutputStream(f);
  40. bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
  41. out.flush();
  42. out.close();
  43. }
  44. catch (Exception e)
  45. {
  46. e.printStackTrace();
  47. }
  48. }
  49. if (null != activity.getHandler())
  50. {
  51. Message msg = new Message();
  52. msg.obj = result;
  53. msg.what = R.id.decode_succeeded;
  54. activity.getHandler().sendMessage(msg);
  55. }
  56. }
  57. else
  58. {
  59. if (null != activity.getHandler())
  60. {
  61. activity.getHandler().sendEmptyMessage(R.id.decode_failed);
  62. }
  63. }
  64. }

界面自定义扫描框,可在CaptureActivity中自定义即可。也可仿照ZXing的ViewfinderView界面编写自己的布局。

 

Android快速实现二维码扫描–Zxing

Android中二维码扫描的*常用库是zxing和zbar,zxing项目地址为https://github.com/zxing/zxing,目前还有多个人在维护。zbar主要用C来写的,对速度有要求的可使用zbar,但目前没有在维护,项目地址:https://github.com/ZBar/ZBar。

1.引入jar包

%title插图%num

2.copy Zxing包到项目

%title插图%num

这里包名不一样肯定会报错,我们暂时不管,先把资源文件copy过来,后面来做处理。

3.导入相关资源文件

copy res底下的相关资源文件,如下:
drawable、drawable-hdpi和layout

%title插图%num

raw文件和values文件

%title插图%num

4.AndroidManifest.xml加入相关权限和扫描的Activity

<uses-permission android:name=”android.permission.CAMERA” />
<uses-permission android:name=”android.permission.INTERNET” />
<uses-permission android:name=”android.permission.VIBRATE” />
<uses-permission android:name=”android.permission.FLASHLIGHT” />
<activity
android:name=”.zxing.android.CaptureActivity”
android:screenOrientation=”portrait”
android:theme=”@android:style/Theme.NoTitleBar” />
6.capture.xml的ViewfinderView改成自己包名下的

%title插图%num

7.调起扫描界面 获取扫描结果

在需要打开扫描界面的地方直接跳转到CaptureActivity就OK(使用startActivityForResult)

/**
* 跳转到扫码界面扫码
*/
private void goScan() {
Intent intent = new Intent(MainActivity.this, CaptureActivity.class);
startActivityForResult(intent, REQUEST_CODE_SCAN);
}
在onActivityResult的回调中即可获取扫描内容

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// 扫描二维码/条码回传
if (requestCode == REQUEST_CODE_SCAN && resultCode == RESULT_OK) {
if (data != null) {
//返回的文本内容
String content = data.getStringExtra(DECODED_CONTENT_KEY);
//返回的BitMap图像
Bitmap bitmap = data.getParcelableExtra(DECODED_BITMAP_KEY);
}
}
}
动态权限申请

由于扫描需要调用相机,打开摄像头属于敏感权限,所以需要进行权限的动态申请,如下

//动态权限申请
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CAMERA}, 1);
} else {
//扫码
goScan();
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
case 1:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//扫码
goScan();
} else {
Toast.makeText(this, “你拒*了权限申请,无法打开相机扫码哟!”, Toast.LENGTH_SHORT).show();
}
break;
default:
}
}
上面的代码就是动态申请权限的流程,首先判断用户是不是已经给我们权限授权了,使用ContextCompat.checkSelfPermission()方法,*个参数是Context,第二个参数是具体的权限名称,如果等于PackageManager.PERMISSION_GRANTED表明已授权,不等于就是没有授权。
如果已授权就直接做后面的操作,如果没有授权,需要调用ActivityCompat.requestPermissions()方法申请授权,*个参数是当前Activity实例,第二个参数是权限数组,第三个是请求码。
用户的选择将会回调到onRequestPermissionsResult()方法中,授权结果封装在grantResults参数中,如果grantResults长度大于0且grantResults[0]等于PackageManager.PERMISSION_GRANTED,也就是上面权限数组中加入的*个打开摄像头的权限被授权,则可跳转至扫描界面扫码,否则提示用户未打开权限无法使用。

android利用zbar二维码扫描

之前用zxing做开发,各种奇葩问题,横屏修等等,而且性能也不搞。被测试批了,没办法后来换了zbar。性能好多了。

/*********************重要更新*******************************/

有朋友提到两个问题:

1.扫描框目前只是做的假象,是全屏的图片进行解析

2.中文乱码现象

以上两个问题已经得到解决

/*************************/

直接上图,看看效果

%title插图%num

2.界面上的查找框

/**
* 2014-7-15 上午11:14:21
* Created By niexiaoqiang
*/

package com.example.qu;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;

/**
* 查找框
* @author niexiaoqiang
*/
public class FinderView extends View {
private static final long ANIMATION_DELAY = 30;
private Paint finderMaskPaint;
private int measureedWidth;
private int measureedHeight;

public FinderView(Context context) {
super(context);
init(context);
}

public FinderView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRect(leftRect, finderMaskPaint);
canvas.drawRect(topRect, finderMaskPaint);
canvas.drawRect(rightRect, finderMaskPaint);
canvas.drawRect(bottomRect, finderMaskPaint);
//画框
zx_code_kuang.setBounds(middleRect);
zx_code_kuang.draw(canvas);
if (lineRect.bottom < middleRect.bottom) {
zx_code_line.setBounds(lineRect);
lineRect.top = lineRect.top + lineHeight / 2;
lineRect.bottom = lineRect.bottom + lineHeight / 2;
} else {
lineRect.set(middleRect);
lineRect.bottom = lineRect.top + lineHeight;
zx_code_line.setBounds(lineRect);
}
zx_code_line.draw(canvas);
postInvalidateDelayed(ANIMATION_DELAY, middleRect.left, middleRect.top, middleRect.right, middleRect.bottom);
}

private Rect topRect = new Rect();
private Rect bottomRect = new Rect();
private Rect rightRect = new Rect();
private Rect leftRect = new Rect();
private Rect middleRect = new Rect();

private Rect lineRect = new Rect();
private Drawable zx_code_kuang;
private Drawable zx_code_line;
private int lineHeight;

private void init(Context context) {
int finder_mask = context.getResources().getColor(R.color.finder_mask);
finderMaskPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
finderMaskPaint.setColor(finder_mask);
zx_code_kuang = context.getResources().getDrawable(R.drawable.zx_code_kuang);
zx_code_line = context.getResources().getDrawable(R.drawable.zx_code_line);
lineHeight = 30;
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
measureedWidth = MeasureSpec.getSize(widthMeasureSpec);
measureedHeight = MeasureSpec.getSize(heightMeasureSpec);
int borderWidth = measureedWidth / 2 + 100;
middleRect.set((measureedWidth – borderWidth) / 2, (measureedHeight – borderWidth) / 2, (measureedWidth – borderWidth) / 2 + borderWidth, (measureedHeight – borderWidth) / 2 + borderWidth);
lineRect.set(middleRect);
lineRect.bottom = lineRect.top + lineHeight;
leftRect.set(0, middleRect.top, middleRect.left, middleRect.bottom);
topRect.set(0, 0, measureedWidth, middleRect.top);
rightRect.set(middleRect.right, middleRect.top, measureedWidth, middleRect.bottom);
bottomRect.set(0, middleRect.bottom, measureedWidth, measureedHeight);
}
}

2.扫描的activity
package com.example.qu;

import net.sourceforge.zbar.Config;
import net.sourceforge.zbar.Image;
import net.sourceforge.zbar.ImageScanner;
import net.sourceforge.zbar.Symbol;
import net.sourceforge.zbar.SymbolSet;
import android.app.Activity;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PreviewCallback;
import android.hardware.Camera.Size;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class MainActivity extends Activity implements SurfaceHolder.Callback {
private Camera mCamera;
private SurfaceHolder mHolder;
private SurfaceView surface_view;
private ImageScanner scanner;
private Handler autoFocusHandler;
private AsyncDecode asyncDecode;

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

private void init() {
surface_view = (SurfaceView) findViewById(R.id.surface_view);
mHolder = surface_view.getHolder();
mHolder.addCallback(this);
scanner = new ImageScanner();
scanner.setConfig(0, Config.X_DENSITY, 3);
scanner.setConfig(0, Config.Y_DENSITY, 3);
autoFocusHandler = new Handler();
asyncDecode = new AsyncDecode();
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (mHolder.getSurface() == null) {
return;
}
try {
mCamera.stopPreview();
} catch (Exception e) {
}
try {
mCamera.setDisplayOrientation(90);
mCamera.setPreviewDisplay(mHolder);
mCamera.setPreviewCallback(previewCallback);
mCamera.startPreview();
mCamera.autoFocus(autoFocusCallback);
} catch (Exception e) {
Log.d(“DBG”, “Error starting camera preview: ” + e.getMessage());
}
}

/**
* 预览数据
*/
PreviewCallback previewCallback = new PreviewCallback() {
public void onPreviewFrame(byte[] data, Camera camera) {
if (asyncDecode.isStoped()) {
Camera.Parameters parameters = camera.getParameters();
Size size = parameters.getPreviewSize();
Image barcode = new Image(size.width, size.height, “Y800”);
barcode.setData(data);
asyncDecode = new AsyncDecode();
asyncDecode.execute(barcode);
}
}
};

private class AsyncDecode extends AsyncTask<Image, Void, Void> {
private boolean stoped = true;

@Override
protected Void doInBackground(Image… params) {
stoped = false;
Image barcode = params[0];
int result = scanner.scanImage(barcode);
if (result != 0) {
// mCamera.setPreviewCallback(null);
// mCamera.stopPreview();
SymbolSet syms = scanner.getResults();
System.out.println(syms);
for (Symbol sym : syms) {
Log.d(“xiaoqiang”, sym.getData());
}
}
return null;
}

@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
stoped = true;
}

public boolean isStoped() {
return stoped;
}
}

/**
* 自动对焦回调
*/
AutoFocusCallback autoFocusCallback = new AutoFocusCallback() {
public void onAutoFocus(boolean success, Camera camera) {
autoFocusHandler.postDelayed(doAutoFocus, 1000);
}
};

//自动对焦
private Runnable doAutoFocus = new Runnable() {
public void run() {
if (null == mCamera || null == autoFocusCallback) {
return;
}
mCamera.autoFocus(autoFocusCallback);
}
};

@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera = Camera.open();
} catch (Exception e) {
mCamera = null;
}
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mCamera != null) {
mCamera.setPreviewCallback(null);
mCamera.release();
mCamera = null;
}
}
}

 

想换小米 11pro,有用过的进来说说优缺点

因为公司可以报销电话费 300,打算去联通商店里买套餐,买 329 的套餐,买 24 个月,自己再出 1600 可以换一台小米 11pro,貌似换 iphone12 要自己掏出 3100,纠结中。。。。主要是屏幕小米 11pro 是 6.8 的,还带长焦。。。iphone 要 pro max 才可以

murmur
    1

murmur   1 天前   ❤️ 3

买红米,就小米对旗舰机的态度,恕我直言,谁买谁 sx

真的不值,价格上去了,待遇没上去,广告和 bug 一个不少,买红米的话你觉得赚爆了,买小米旗舰机,图的是啥

cybermonster
    2

cybermonster   1 天前   ❤️ 1

@murmur 草,小米 11 pro 那么糟糕????
murmur
    3

murmur   1 天前

@cybermonster 首先小米 11p 用的晓龙 888 在今年就是个负优化,然后就是 miui 漫山遍野的广告,*后是 miui12.5 各种层出不穷的 bug

相机调教我认为都是朋友圈扫码级别,也不和专业相机拼,网上都会建议你装谷歌相机和配置,原因可想而知

长焦,算了把,手机长焦跟相机长焦比

x86
    4

x86   1 天前

K40 还算舒服,就是后面丑了点
sks4728
    5

sks4728   1 天前

手持小米 11 劝你 不要买小米
66beta
    6

66beta   1 天前   ❤️ 1

没那么不堪,主要是重量劝退,当然,iphone 12 的手感也劝退
cybermonster
    7

cybermonster   1 天前

@sks4728 那么差????
Cyshall
    8

Cyshall   1 天前

据了解,小米 11 就拉垮在 CPU 上吧,发热太严重了。如果非要在小米 11 和 iPhone 12 之间选,我建议 12,如果扩大范围,我建议上一代安卓旗舰。
xloger
    9

xloger   1 天前   ❤️ 17

额,本来不想回帖的,看到了 1 楼…
我手头是小米 11,不是 pro 。广告没多少,bug 也没多少。而且说到广告,起码小米的广告开关是符合用户直觉的,我直接就关了。我手头有台华为测试机,某天突然桌面冒出一个啥精品推荐,我绞尽脑汁都不知道怎么删掉,*后还是靠搜索…而且华为自带的视频播放器都有关不掉的视频推荐(关闭内容后也有一个恶心的 icon 在那)。其他厂商这几年的手机我没用过,我是真不明白那些说小米广告多的人怎么看华为的。

然后续航问题,MIUI12 的时候我手头这破手机续航一天一冲都不够,换成 12.5 后倒是一天一冲没啥问题了。相机我不懂用的也不多,个人感受:1 、微信自带的拍照功能渣得一逼,效果远比系统自带的差。要拿其他的比我不说话,拿微信拍照比,呵呵。2 、微距功能挺好玩,但是拍出来后总有点糊。当然,我这是 11 不是 pro 。

个人真实感受。你要不认也没问题。

cybermonster
    10

cybermonster   1 天前

@xloger 卧槽,一天要 2 冲????
murmur
    11

murmur   1 天前

广告这个问题,我认为 对于 11pro 这种旗舰机,就应该学魅族直接默认全关闭,11pro 下面有 10 有红米,那么多机器还在乎旗舰机的广告费,如果你是买红米,广告补贴机器我都不说什么,11pro 可是旗舰啊,不会有人认为折叠屏这种工业垃圾才是旗舰机吧

华为,怎么评价,当然是他都没货了我无话可说

摄像,有人似乎曲解了我的问题,我的意思是,日常生活看不出区别,就算你买红米他肯定都是够用,专业摄影不够,至少态度上我认为你没人用单反的端正。

ybbswc
    12

ybbswc   1 天前   ❤️ 3

我觉得小米好像真的没有审美似的。
旗舰机做得丑哭了。
subpo
    13

subpo   1 天前

手持 11,一切都挺好,屏幕尤其好
就是下单的时候手滑买成 128G,蛋疼,在国外还不方便换,只能勉强用了
xloger
    14

xloger   1 天前

@cybermonster #10 以前 MIUI 12 的时候是这样,当然我是 2k +120hz 都开了的。那时候每天中午都会打会炉石。然后下午四五点就没电了,而且大部分时候其实我是在用电脑,没咋开手机。
现在 12.5 好挺多,晚上到家还有个 20% 吧,我能接受了。
Asan
    15

Asan   1 天前

我劝你善良,不要买小米,用着恶心,小米 11 现在成视频播放器了,yysy,屏幕和音响不错
isnullstring
    16

isnullstring   1 天前

旗舰机也有广告…..也没见便宜哪里去
vazo
    17

vazo   1 天前   ❤️ 1

纯从硬件参数看 Xiaomi mi 11 Pro 优于 Apple iPhone 12,例如电池容量 /屏幕像素密度解析度 /随机存取记忆体容量 /摄像头解析度分辨率,供参考.
Inozo
    18

Inozo   1 天前

手持 11 除了 120hz 2k 带来的耗电,其他的都不错
251243021
    19

251243021   1 天前   ❤️ 1

没人觉得 miui12 严重拖垮机子嘛
YIFZ
    20

YIFZ   1 天前

手持小米 11Ultra,毕竟屏幕配置太高,耗电确实快,但是一天不怎么玩游戏,也可以使用快 4 小时,发热来讲,用的多也就 40 度,不太高,玩游戏就高了。
堆料配置同价位顶级,骁龙 888 发热大,哪款手机都差不多
MUUI 广告都可以关闭,总比有的手机广告多还没法关好多了吧
yuuko
    21

yuuko   1 天前

手持小米 10 至尊版,我劝你不要买小米旗舰手机,系统对不起硬件,现在 MIUI 12 bug 无数,反馈都没人理,一个 bug 好几个月都不修。还有就是旗舰机的特有的功能,随着更新更新着就没了
shuxhan
    22

shuxhan   1 天前

红米真的丑哭我
yuuko
    23

yuuko   1 天前

@251243021 再同意不过了,120 刷新经常给我来几下到 60 刷新的感觉,有时候系统动画用着突然变快了,像开了加速一样。。。日常使用 N 多小问题。系统通知点开变透明反馈了好几个月了都没人修,负一屏每次都是加载加载
lysS
    24

lysS   1 天前   ❤️ 1

”起码小米的广告开关是符合用户直觉的“ 也是够好孝的
lakehylia
    25

lakehylia   1 天前

小米 6 不给升级 miui12 之后,我就转到菊厂了。。。
cybermonster
    26

cybermonster   1 天前

@yuuko 卧槽,小米 10 至尊版还是很好看的
shenjinpeng
    27

shenjinpeng   1 天前

小米就是个水桶机, 你想要的功能他都有 , 618 活动也给力 . 喜欢折腾的自己关一下广告也还行, miui 现在是真的拉胯. 很多 ui 普普通通估计是大街上捡来的设计师设计的, 整体风格也不搭 , 很多系统应用惨不忍睹 . 总的来说用起来没有 ios 优雅 , 但是硬件配置是真的高 , 功能也全 . NFC 刷门禁 公交 地铁 充 ETC , 摄像头的话不用太纠结, 旗舰机差距不是很大, 长焦没多大用, 拍出来一般般 ,能看.
yousabuk
    28

yousabuk   1 天前 via iPhone   ❤️ 2

买手机系统自带系统级广告,这都能忍,还说可以关呀?

疯了啊,容忍度是有多低。

BBCCBB
    29

BBCCBB   1 天前   ❤️ 2

广告, 权限, 恶意推送, 我再也不想用安卓了…
BBCCBB
    30

BBCCBB   1 天前

安卓旗舰也有广告这太离谱了
tyzrj766
    31

tyzrj766   1 天前

MIUI12.5 太拉,多少年的米粉都看不下去了,硬件方面倒是没啥毛病,小米每年都这样,旗舰机没设计,硬件堆料够,软件必拉垮
Nuttertoo1s
    32

Nuttertoo1s   1 天前

我朋友是卖手机的,小米利润是*低的卖一台 200 左右,OPPO 利润是*高的 500-1000
nuxio
    33

nuxio   1 天前

刚换的 11pro,机身比较重,摄像头模块非常突出,丑的一 p 。。屏幕素质优秀,比起我的三星 2k 多了 120hz 刷新率,看起来非常丝滑。miui 界面和动画都很像 ios… 但是不太稳定,不时会有掉帧的情况。发热是真的,用的时候基本都是温热状态,烫手倒是还没遇到过(平时就看 b 站和偶尔玩王者)。续航的话就一天一充。
ciming
    34

ciming   1 天前

去 b 站搜一圈小米,基本都对 mi11 及 miui12 骂声一片,连死忠米粉都控不了评
LZSZ
    35

LZSZ   1 天前

感觉还没有魅族 18pro 好,当然我是完全凭感觉,两个机器我都没用过。
Mcx
    36

Mcx   1 天前

miui 又丑又卡(但是功能性没得说),建议考虑其他机型
pipilu
    37

pipilu   1 天前

没有辨识度,要买就买 ultra
Chihaya0824
    38

Chihaya0824   1 天前

小米 11 (非 pro )备用机主力机 iPhone,作为备用机他非常好,然后其实完全不用担心电池的问题,用了就回不去的屏幕(直到我用了 21 年的 ipad pro12.9),以及算是高素质的音响(但是个人觉得和小米 10 有那么一些退步)。 续航可以说是比较差了,2k+120hz 就是耗电,基本上只能用 6 个半小时的亮屏。但是就算用到没电,中午插上电睡觉,半小时之后就基本充电好了。 然后至于小米的系统,能用但用的舒服不舒服,看你觉得动动手指关一下广告这个操作所给你带来的心理感受是不是你所能承受的了。(如果之前用的是小米,这个操作是会被继承的,在上一个小米机器上关了,恢复数据以后这个小米会继承你上一个小米的广告设置,所以我这边的体验就像是没有广告一样)
不过我这只是站在备用机的视角,大部分时间是用来开发测试用的。刚需 app 并没有在它上使用,体验应该是有差异的,仅供参考。
JensenQian
    39

JensenQian   1 天前 via Android

这玩意硬件是顶级的水桶机,但是今年 888 翻车加上现在拉跨的 MIUI,所以劝你思考一下
这玩意东哥家前几天九折消费券 8+128 都干到 3899 了
Chihaya0824
    40

Chihaya0824   1 天前

@Chihaya0824 基本上我对 MIUI *讨厌的地方就是它的广告,其他还是相当流畅的,还有提一句 888 是真的烫,但这实在是没办法
JensenQian
    41

JensenQian   1 天前 via Android

@JensenQian 用的惯果机的话买 12 吧,或者你干脆等 13 吧,也不用这几天帮库克清库存
a11214214
    42

a11214214   1 天前

– -米 10S 用户控诉
1. 号称旗舰,12.5 适配慢 bug 也多
2. 卖点哈曼卡顿 直接 OTA 砍没了
3. 现在的小米不是当初 刷开发、内测版都得审核等等等等 再也不是当初搞机的小米了
4. 论坛骂声一片,感觉是开发版的 bug 到稳定版还在
5. 广告…真心还行吧 不会觉得很多 没啥感受到的
bequt
    43

bequt   1 天前

这玩野是跳水机,直接跳水 2000+,大概就知道这机子什么水平了。肯定是买的人少,硬件贬值快。
小米还是建议买*便宜的 k40 即可
jumpiz
    44

jumpiz   1 天前

mi10 用户,miui12.5 拉了
felixliu95277
    45

felixliu95277   1 天前

建议 870 or 下一代,不推荐 888
ToxicPorridge
    46

ToxicPorridge   1 天前

手持 11pro,没毛病。建议购买,重了点,发热压制并没有特别好,毕竟火龙 888,其他基本完美(价格跳水)。*惊艳的是双扬声器的音质和屏幕
DiverO
    47

DiverO   1 天前

太重
yueban5521
    48

yueban5521   1 天前

自己去实体店体验下对比下,流程度都差不多,广告不至于都是一些推荐,很好关,每家都有,就是有点大重,音效和屏幕真没得说,特别是音效很舒服,还有就是既然考虑红米那就去买呗,使用上差不多,游戏不卡,拍照能看,还便宜
limuyan44
    49

limuyan44   1 天前

狗日的 k30 没 root,谷歌全家桶用了很久前阵子也割了好了几天之后又割了,设置里去广告不到 1 个小时又回来了,给第三方应用加启动页广告,连后台切前台都加还是*恶心的碰到就下载的广告,这个功能是小米提供给开发者的的,可是 tm 的傻叉小米只认包名不认开发者,要不是腾讯做的大你甚至可以拿着微信的包名提供给小米,从此小米手机上的微信就有了开屏广告。除开这些,miui 唯一可取的地方也就权限管理了,不过我觉得各家厂商应该都会往这方面努力, 总之一句,傻叉雷军金凡,miui 回家吃屎吧,用过一次小米不想用了。另外,刚看雷军微博似乎某款手机十天降了 1000 元,确实业界良心。
mwVYYA6
    50

mwVYYA6   1 天前

@murmur 买小米的*步就是看有没有类原生系统可以刷,要是 Pixel Experience 支持小米 11 了,那小米 11 才无敌。
xinlinqi
    51

xinlinqi   1 天前

在用,感觉还挺好的。上一部手机是苹果 X,屏幕、续航、系统流畅度等比苹果 X 好多了,特别是*次用快充,有点爽。相机拍照是个短板,手动放大后看不到细节
XiaoBaiYa
    52

XiaoBaiYa   1 天前

888 真的别买
NovemberEleven
    53

NovemberEleven   1 天前

2 月 1 号买的小米 11,上个星期一后置摄像头坏了,去小米之家检查需要换主板,等了一个星期,预约明天去还新主板,希望没问题。
NovemberEleven
    54

NovemberEleven   1 天前

还有小米之家的人,留了微信联系,问进度老是不回复,一定要我打电话过去。
mcluyu
    55

mcluyu   1 天前

自从小米 Note 顶配版后就下猴山了,很庆幸早点脱离,没想到多年后依然还是那个尿性,各种参数吹上天,什么都是世界*,实际体验啥也不是。
Zhancha
    56

Zhancha   1 天前

能上 iphone 就 iphone 吧
shunia
    57

shunia   23 小时 58 分钟前   ❤️ 1

你不对劲,你应该说你想买华为
um1ng
    58

um1ng   23 小时 55 分钟前

5050 iPhone 12 128G 不香吗?
Cola90
    59

Cola90   23 小时 53 分钟前

米 10p 用户,升级 12.5 后米粉转米黑,bug 严重到没法忍,准备换了
bingyiyu
    60

bingyiyu   23 小时 43 分钟前

满屏的吐槽小米,看来手上的 1+7t 还能再战一年。不过好像以后原装的氢氧要变成 colorOS 了
justrand
    61

justrand   23 小时 40 分钟前

确实有广告,我是看到广告再一个个关掉的,关闭的地方有的比较隐蔽,但是关掉后,基本上一片清净了。
cybermonster
    62

cybermonster   23 小时 33 分钟前

看来还是吐槽的是多数
dinghmcn
    63

dinghmcn   23 小时 26 分钟前

888 很烫吧,考虑 87 的红米 k40 或小米 10S,红米 k40 pro 也是 888 的
nexuszjq
    64

nexuszjq   23 小时 16 分钟前

先不说这代小米旗舰外观丑(或者说是设计不精致),核心竞争力的 MIUI 口碑还倒了。。。
yangxiaopeipei
    65

yangxiaopeipei   23 小时 15 分钟前

缺点不就是 MIUI 吗
zhangslob669
    66

zhangslob669   23 小时 12 分钟前

手持 11pro,从 11 换过来的

优点:
1. 屏幕好,2K 真的舒服
2. 续航、拍照比 11 好一些
3. 亮屏 5 小时+
4. MIUI 广告基本可以关闭,App 开屏广告用一指禅

缺点:
1. 发热很严重,40°正常,夏天必须在空调房才敢放心玩
2. 有点重,单手操作不大方便
3. 8G 内存不太够,如果买建议 12G
4. 时不时出一些 bug,比如有 WiFi 连不上,内部软件闪退

系统版本:稳定版 12.5.7

个人下一部手机不会再用小米了,可能会选红米。如 K40 游戏版

JensenQian
    67

JensenQian   23 小时 12 分钟前 via Android

@bingyiyu 氢变 color,海外的氧还在
funbox
    68

funbox   23 小时 9 分钟前

有点烫手
StopTheWorld
    69

StopTheWorld   22 小时 50 分钟前

七年小米用户告诉你,11pro 是我用的*后一台小米,以后不会再买了,当猴当累了。
yuniorzy
    70

yuniorzy   22 小时 48 分钟前

作为曾经的小米 8 和小米 10 用户,劝楼主别买小米。。长期使用下来的体验,真的一言难尽
zhaole
    71

zhaole   22 小时 47 分钟前

买三星!建议完毕
hshpy
    72

hshpy   22 小时 46 分钟前

小米 10S 到手后在设置关掉系统广告,个性化广告推荐,智能服务,现在用着感觉还能接受…
看到的广告 iOS 上面也有,app 启动页广告,滚动图广告(视频 app 推荐剧)这些得小火箭中间人劫持去广掉才行,麻烦很少人弄。
calano
    73

calano   22 小时 40 分钟前

@yousabuk 我就是被这话忽悠了,换了 oppo 发现一点不少,连关的选项都没,拿其他人 hw 玩发现也有,只不过玩的时间短,感觉没那么多
K1W1
    74

K1W1   22 小时 35 分钟前 via Android

用的小米 10+MIUI12.5,很舒服
dianso
    75

dianso   22 小时 28 分钟前 via Android

小米 11 经常重启 下乡没网 幸好我还有个 m40 备用
KrisWuSkrSkr
    76

KrisWuSkrSkr   22 小时 21 分钟前

你之前用的啥,之前用的小米,可以买。要不是,不推荐。
adminharlem
    77

adminharlem   21 小时 50 分钟前

@xloger #9 华为的广告真的很难找到关闭入口的,下拉搜索也是一堆广告
EakingYu
    78

EakingYu   21 小时 42 分钟前

用了六年小米,*近换 iPhone12.实际体验还是 iPhone 好一点,动画舒服 app 也很美观.miui 也没有说的那么不堪.现在手机差别不大了,喜欢啥外观就买啥
cuicuiv5
    79

cuicuiv5   21 小时 41 分钟前 via Android

坐等 mix4
ubbcou
    80

ubbcou   21 小时 41 分钟前

老实说我喜欢 iphone12 的棱角,不喜欢圆润的背面。
Lemeng
    81

Lemeng   21 小时 39 分钟前

个人观感不一样,建议去专卖店看看,手感各方面,体验体验
faqqcn
    82

faqqcn   21 小时 38 分钟前

首发的 11pro 顶配,结果两个月就跳水 1000+,以后得观望了。

不开 2k120 的话,电池还是很给力的

JackyCDK
    83

JackyCDK   21 小时 34 分钟前

小米买双不买单(
fanlis
    84

fanlis   21 小时 34 分钟前

手机一直用华为想说一句,之前华为的系统应用连启动页都是没有广告的,现在不知道怎么从什么版本开始,广告都加上了,虽然有关闭广告的按钮,但是并没有那么有效,*多在隐私设置限制广告跟踪
fanlis
    85

fanlis   21 小时 33 分钟前

在意广告就别考虑小米华为了,买 1+吧
cybermonster
    86

cybermonster   21 小时 32 分钟前

@zhangslob669 我不玩游戏,发热也那么严重吗???拍照除外
cybermonster
    87

cybermonster   21 小时 32 分钟前

@fanlis 我现在就是 1+用户,但是大氢亡了。。。
cybermonster
    88

cybermonster   21 小时 30 分钟前

@StopTheWorld 草,那么不堪!
cybermonster
    89

cybermonster   21 小时 29 分钟前

@YIFZ 11ultra 要贴 3100,想了想毛爷爷得微笑,觉得还是选 11 pro 好
cybermonster
    90

cybermonster   21 小时 27 分钟前

@Chihaya0824 有些人说广告可以关,到底全部关得掉吗?我手上的 1+真的是没广告,启动广告也没办法。。。
lonelymarried
    91

lonelymarried   21 小时 23 分钟前

用的三星 note9 和 iphone 11,啥是广告?
zhangslob669
    92

zhangslob669   21 小时 4 分钟前

@cybermonster 我看直播也发热严重
Chihaya0824
    93

Chihaya0824   21 小时 3 分钟前

@cybermonster 除了短信里藏广告这个提示不明显( https://v2ex.com/t/779241 )和旧版本红外遥控器似乎没办法关闭广告以外,系统应用都能关闭广告,甚至可以”卸载“(实际上似乎是隐藏)。不过都要在设置里翻一下,有些广告并不是在系统设置里关闭就完全关闭的,还要去单独的应用里:如“安全中心” 到右上角里面关闭广告。强烈推荐不用小米自己的应用商店和浏览器,直接 Google play 和 chrome 完事,自带的系统应用商店就是个广告商店,然后如果不小心点进去了以后可以清除那个 app 的数据,不同意协议的状态一般不会给你推送任何信息,包括广告。
lonelymarried
    94

lonelymarried   20 小时 49 分钟前

小米还造车呢
bluecrow
    95

bluecrow   20 小时 49 分钟前 via Android

听我一句劝,省这 1500 到时后悔药没地买去
sks4728
    96

sks4728   20 小时 46 分钟前

@cybermonster
2k +120hz 轻度使用, 不打游戏 一天一充,
小 bug 挺多 没有严重的
广告要自己关,
前端时间刷贴吧都发热严重,*新版系统降频了,好了点(骚操作)
摄像头一直都是够用就好 不做评论,
disonlee
    97

disonlee   20 小时 46 分钟前

现阶段 iphone 还是优选(个人意见,杠就你对)
Gamanc
    98

Gamanc   20 小时 43 分钟前

说实话 不买小米就是一个 life pro tip
nullboy
    99

nullboy   20 小时 17 分钟前

小米 11 时不时发烫的厉害
supersu
    100

supersu   20 小时 17 分钟前 via Android   ❤️ 2

别买小米 11 系列,难道没听说 11 系列少则几百多则上千的烧主板案例么,自行微博搜索一下“小米 11 主板”,手持米 11,每天心惊胆战的用手机~
shyrock
    101

shyrock   20 小时 18 分钟前

差价 1500,现在这物价也就是出去吃两顿饭的钱。。。
为了今后三年不糟心,还是 12 吧
OldJii
    102

OldJii   20 小时 5 分钟前

以前用的什么系统就买什么的吧,别换系统了
amusier
    103

amusier   19 小时 48 分钟前

手持小米 11PRO 回答:

从华为 MATE40PRO 换回来的,换小米的原因是:华为这款手机的屏幕素质太差。

体验如下:
1 、手感:滑溜,建议用手机壳,我目前用的是液态硅胶壳,正面没有贴膜。
2 、系统:MIUI12.5,怎么说呢,MIUI *早是小米引以为傲的资本,*近几年友商进步速度挺快,MIUI 进步小一些,BUG 有,但没有网上说的那么严重。(我用的是乌堆小透明的第三方 ROM,详情可去酷安搜索)
3 、拍照:比我用了两个月的华为 MATE40PRO 差点,主要是长焦方面不行,10 倍以上变焦拍照时不如华为那么稳。但对*大多数人来说,够用了。
4 、能耗:2K+120,亮屏 6-7 个小时吧,说实话,不如华为 M40P 的续航,但是,好在 67W 充电速度很快,也能接受。
5 、发热:高通骁龙 888 处理器,充电的时候使用的话,能到 42 度,略热。因为我不玩崩坏、吃鸡等大型游戏,日常使用可以接受。
6 、其他:小米手机是现在为数不多的可以解锁并刷第三方 ROM 的手机了吧,之后就可以享受面具、框架带来的真正好玩的安卓系统了,何乐而不为呢?

目前发现的 BUG:
1 、接电话之后,离开脸部,偶尔会不亮屏(之前用 MIX2S 的时候就如此,应该是距离感应器不好用)
2 、解锁的一瞬间会黑屏一下,应该是*新版 MIUI 的锅,论坛有人反映过,后期估计会修复。

就这样。

Cookieeeeee
    104

Cookieeeeee   19 小时 22 分钟前

以前用的什么系统就买什么的吧,别换系统了
yi0322
    105

yi0322   19 小时 8 分钟前

你买个 iPhone12 128G, 我可以用 99 新 ultra 给你换, 哈哈
Maskeney
    106

Maskeney   18 小时 44 分钟前

@cybermonster 大氢本来是个好东西,但是 OP 在不讲究的道路上越走越远,*后导致大氢的系统组件几乎全都是 OPPO 欢太了,逐渐变成了个不伦不类的东西,何必留恋
DhhhhhhL
    107

DhhhhhhL   18 小时 36 分钟前

建议 iphone,用两年 1500 卖了无损
johnsonshu
    108

johnsonshu   17 小时 20 分钟前

@limuyan44 怎么判断 APP 启动广告是 MIUI 给加的,还是说 APP 自带的?
sosilver
    109

sosilver   16 小时 10 分钟前 via Android

miui 某些地方的广告开关在系统没更新的情况下还会自己打开,细品一下
ipooooo
    110

ipooooo   15 小时 33 分钟前   ❤️ 2

我是小米员工 请直接买苹果
20015jjw
    111

20015jjw   14 小时 47 分钟前

别搞自己,国内还是老老实实 iPhone
Donahue
    112

Donahue   14 小时 22 分钟前

小米不要买高端,一两年就贬值到 1000 块钱,参考小米 9 现在价格跟同期出的二手 iphone 价格~
所以纠结这 1500 的话就买 iphone 12, 强烈推荐~过两年换手机的时候,按照两个贬值速度不同,应该是赚的。
家里 3 台红米 k20pro, 一台小米 9 的路过~
cmdOptionKana
    113

cmdOptionKana   14 小时 22 分钟前   ❤️ 1

我现在用红米 k30pro 很满意,小米 11 竟然更差吗?

– google play 市场可以直接安装
– 不管 wifi 还是流量信号都明显比 iphone 强
– 广告关了,然后垃圾电话、垃圾短信可以方便屏蔽,来电还能提醒是快递还是推销,又有电话录音
– 更低的价格,容量却比 iphone 大很多(大优点)!
– 充电快,电量持久
– NFC 功能也比 iphone 方便

优点很多呀

cmdOptionKana
    114

cmdOptionKana   14 小时 12 分钟前

还有日历有农历和中国假期,闹钟可以自动适配假期,这些小细节也比 iPhone 好。

信号、垃圾电话识别、电话录音、低价格大容量、更符合本土习惯的细节(比如日历、闹钟),这几点我认为是*大的优点,对日常使用的影响也很大。

而不用搞一个随时可能被封的外国账号也能安装全球各国的 app,这点是我从 iPhone 转到安卓的*大原因。

digman
    115

digman   13 小时 13 分钟前 via Android

配置还是很强大的, 小米也有多屏协同, 可能系统稳定性方面不如 oppo 及 vivo 。
VENIVIDIVICI
    116

VENIVIDIVICI   13 小时 1 分钟前

Wifi 烧了,刚去售后修了修
Eagleyes
    117

Eagleyes   5 小时 35 分钟前

@Donahue 小米 9 首发用户,2019 年 2 月买,2999 乞丐版,现在能值 1000 ?掉价 2/3 。

同期 Xr 大概 5000+ ?

现在 Xr 大约 2000,掉价 60%,3000 块。跟小米差不多

fh74599
    118

fh74599   5 小时 33 分钟前

突然觉得手上的米 9 香了,换了大电池,续航一天一充,不带套手感和重量都很舒适
zarvin
    119

zarvin   5 小时 31 分钟前

小米 11 是不是主板有问题,看见好多人说 Wi-Fi 问题
yongzhenchen682
    120

yongzhenchen682   5 小时 21 分钟前

以前还有微博的时候,有一天自动给关注了雷军,小米科技。。我就?
kkjinping
    121

kkjinping   5 小时 9 分钟前

发热是真的很严重,哎
faqqcn
    122

faqqcn   4 小时 48 分钟前

@amusier 我这边偶尔充电拿开后会自动打开相机,不知道什么原因,早上偶尔解锁后会出现无响应 ?
byte10
    123

byte10   4 小时 42 分钟前

听话,买苹果 12,作为一个高手给你的忠告。买苹果三年不用换机器,买安卓一年就厌弃。贬值快,屏幕坏了维修贼贵,苹果的屏幕坏了直接 LCD 屏幕就好了。安卓屏幕容易摔坏,你不听话,以后就会很惨,三年摔三次屏幕,三次屏幕后,你的安卓就要加 2000 。作为先知预言家,你不听我的,以后会吃亏
vone
    124

vone   4 小时 38 分钟前

@byte10 android 机现在屏幕也挺结实的,你说的都是多少年前的情况了吧。
gablic
    125

gablic   4 小时 36 分钟前

看来是我被一加惯坏了,有广告还觉得不正常?
byte10
    126

byte10   4 小时 32 分钟前

@vone LED 容易摔坏。听话,选 iphone,顶级的高手告诉你,选 iphone 就行了。电脑也选 iphone,用起来舒服。window 跟安卓都是一个鬼样,交互设计不行,广告贼多。安卓魅族的交互和小米都还可以,魅族的交互是超越了苹果的,只是国内安卓 APP 坑多。买苹果电脑和手机就对了。不要买 ipad 这种鸡肋的就好,不过非要买平板,也只能买苹果的。其他都咋地。
hereIsChen
    127

hereIsChen   4 小时 31 分钟前

米 11,如果使用频率高至少一天一冲 会发烫
miui12.5 除了空白通行证 其他功能也不是很明显 感觉没啥大用
cybermonster
    128

cybermonster   4 小时 24 分钟前

妈呀,都是来劝退小米 11 系列的。。。。小米 11 真的惨。。。
cybermonster
    129

cybermonster   4 小时 23 分钟前

@ipooooo 你是认真的吗?
allforone
    130

allforone   4 小时 23 分钟前

MIUI 研发部门的大佬都被挖完了还吹 MIUI 呢。升级必出 bug 必卡顿。
cybermonster
    131

cybermonster   4 小时 22 分钟前

@Maskeney 我买一加就是喜欢大氢。。。没了大氢,还能叫一加吗
ccfly
    132

ccfly   4 小时 21 分钟前

看楼上吐槽的我怀疑我用的是不是一个系统了…
我是 5 月换的 11pro,目前用着没遇到过 bug (可能是我运气好?),广告方面也有啥烦的啊,*开始看到关了就再也没出现过。电量的话一天随便用,APP 开屏广告用的一指禅( ios 的开屏没法关)。就我个人而言用起来很满意,没有什么槽点…
cybermonster
    133

cybermonster   4 小时 20 分钟前

@ccfly 手机烫吗?不打游戏。。。就刷微信,贴吧
mastcer
    134

mastcer   4 小时 17 分钟前

@EakingYu 说出你的故事
ccfly
    135

ccfly   4 小时 14 分钟前

@cybermonster 充电时候有点微热 其他时候正常 我偶尔玩炉石和原神 记忆中没出现拿不了的情况
leiiiooo
    136

leiiiooo   4 小时 8 分钟前

Slack 、Webex 等工作软件后台的时候基本收不到信息。已换 SONY
zhangchongjie
    137

zhangchongjie   4 小时 1 分钟前

都这个价钱了,12 不香吗,其实看你到底是想买一堆高配硬件回家还是买一个软硬件合适的系统。我去年从 miui 到 ios 唯一不适应的就是电话 /短信拦截,ios 本地化不是很好
winstars
    138

winstars   3 小时 53 分钟前

买个过得去的手机就行了,不用追求*新 cpu,像 750 这种终端 U 刚刚好,不发热,性能也足够,价格也便宜,两三年换个机,完美迁移。现在用什么品牌,接下也用什么品牌。不要换来换去,会很不适应。
HashV2
    139

HashV2   3 小时 48 分钟前

@amusier #103 对广告没有感到困扰吗?
BrainOnline
    140

BrainOnline   3 小时 28 分钟前

我是小米早期粉丝,脱粉买了 mix2 以后,早期手机还是摩托罗拉 me525 的时期,安卓版本 2.3.4,刷 miui

当时感觉这个 rom 真的好用到起飞,使用体验太完美了

等小米 1 出来果断抢 小米 2 小米 4 mix1 mix2 我都入手了

说到这些不知道有没有资格评价一下小米,如果认为没有,请直接 B 掉我,谢谢

如果你对使用上轻微体验没有要求,可以买小米,但是和我一样,默认一些功能是不可以带广告的,比如输入法,那么还是不要买小米了

我就没讲过广告潜入的这么疯狂的企业

起码也是生态级企业了,还差点这广告费么

提高一下小米用户的使用体验很难么。

shunia
    141

shunia   3 小时 17 分钟前

@fh74599 #118 咋换的,兄弟指条路
amusier
    142

amusier   3 小时 10 分钟前

@HashV2 #139 可以手动关闭,也不算麻烦,之后再无困扰……
coco000
    143

coco000   3 小时 1 分钟前

建议 i12,hr@test.dibiantech.com
lwd219
    144

lwd219   2 小时 36 分钟前

手持小米 11 劝退,原因如下:
1.bug 太多,各种 app 打开使用摄像头功能的时候,就会经常出现卡机,卡死那种;全面屏手势经常无效;信号很差,小区里偏一点的地方都会出现没网的情况( 4G ),宣传号称的 Wi-Fi 手机网络无缝切换根本没感觉,反而感觉很慢;
2.品控太差,电源键音量键过分松动
3.拍照拉胯,女朋友是水果 11,拍的照片对比起来简直不能比
以上内容*对客观公正,之前也是其他安卓,这是*次买小米,真的体验不好
lwd219
    145

lwd219   2 小时 31 分钟前

再加两条,广告太太太多,虽然说可以关,我也没去具体研究;自动光感乱调,有时候突然就变很暗很暗(正常光线下)
imsonder
    146

imsonder   35 分钟前

小米永远是低端产品,配置虽然上去了,但系统做的太差了
Maskeney
    147

Maskeney   33 分钟前

@cybermonster #131 或者你应该试试氧
cybermonster
    148

cybermonster   21 分钟前

妈呀,v2ex 里看来都是小米的受害者。。。。
zyh94946
    149

zyh94946   16 分钟前

@lonelymarried #91 手持三星 s10,刚出炉新鲜的广告,不定时一个*拜或几个月会出现一个
!
zyh94946
    150

zyh94946   11 分钟前

刚发现从截图放大了看下面有行小字,这个广告是可以关的。对于视力不好的人可太不友好了…
fh74599
    151

fh74599   6 分钟前

@shunia 直接淘宝找靠谱的电池然后手机店换或者自己手动换上
zyh94946
    152

zyh94946   1 分钟前

@zyh94946 顺着截图上的退订方法其实无法退订,这个百度网盘三星版是升级后系统自己装的早就被我卸载了。但是有个服务提醒的应用,里面有营销和促销的开关。

android DLNA投屏

android投屏技术的基本原理就是根据DLNA以及UPNP来实现,另外还有些黑科技技术便是根据端口号或者通过广播来用adb下载本身相关的apk来间接实现投屏,当然此处不提及黑科技。原理什么的百度一堆。这里主要讲实现方式和具体实现的代码。

那么,开始开发这玩意的时候肯定要先看看有没有现成的轮子,git上是有轮子的,链接如下:

https://github.com/4thline/cling *基础的包,main类方法中有基础的调用方式

https://github.com/offbye/DroidDLNA 在cling上改动,代码表现为当前设备的媒资资源DLNA投屏,没涉及到相关的网络媒资投屏

 

DroidDLNA 中是有bug的,具体表现在api版本为25以后,是不能投屏的,原因出自AndroidNetworkAddressFactory类中的反射问题,api版本25以后,结果与之前完全不一致,改法已经在cling中完善,代码改动如下:

@Override
protected boolean isUsableAddress(NetworkInterface networkInterface, InetAddress address) {
boolean result = super.isUsableAddress(networkInterface, address);
if (result) {
// TODO: Workaround Android DNS reverse lookup issue, still a problem on ICS+?
// http://4thline.org/projects/mailinglists.html#nabble-td3011461
String hostName = address.getHostAddress();
Log.e(“gjh test Log”, “sdk version=” + Build.VERSION.SDK_INT + “->hostName=” + hostName);
try {
Field field0 = null;
Object target = null;
try {
field0 = InetAddress.class.getDeclaredField(“holder”);
field0.setAccessible(true);
target = field0.get(address);
field0 = target.getClass().getDeclaredField(“hostName”);
} catch( NoSuchFieldException e ) {
// Let’s try the non-OpenJDK variant
field0 = InetAddress.class.getDeclaredField(“hostName”);
target = address;
}
if (field0 != null && hostName != null) {
field0.setAccessible(true);
field0.set(target, hostName);
} else {
return false;
}
} catch (Exception ex) {
log.log(Level.SEVERE,
“Failed injecting hostName to work around Android InetAddress DNS bug: ” + address,
ex
);
return false;
}
}
return result;
}
DLNA轮子中投屏的方法为广播,代码表现为:

private void jumpToControl(ContentItem localContentItem) {

Intent localIntent = new Intent(“com.transport.info”);
localIntent.putExtra(“name”, localContentItem.toString());
localIntent.putExtra(“playURI”, localContentItem.getItem()
.getFirstResource().getValue());
localIntent.putExtra(“currentContentFormatMimeType”,
currentContentFormatMimeType);
try {
localIntent.putExtra(“metaData”,
new GenerateXml().generate(localContentItem));
} catch (Exception e) {
e.printStackTrace();
}
IndexActivity.mTabHost.setCurrentTabByTag(getString(R.string.control));
IndexActivity.setSelect();
this.sendBroadcast(localIntent);
}
当然如果需求为投射本地已经存在的资源的话只要稍微改动下界面和bug即可。

下面说说如何投射网络在线视频。

从上面的DLNA播放本地资源已经大致可以猜到只要修改其中的name、playURI和metaData即可。

但实际上我们只要改动metaData,因为*终解析是根据MetaData来拿到相关的媒资数据,其他大致上没什么用处

具体实现的代码如下:

 

private AndroidUpnpService upnpService;//DLNA投屏服务
private DeviceListRegistryListener deviceListRegistryListener;//搜索设备的回调
mContext.bindService(
new Intent(mContext, AndroidUpnpServiceImpl.class),
serviceConnection, Context.BIND_AUTO_CREATE);
private ServiceConnection serviceConnection = new ServiceConnection() {

public void onServiceConnected(ComponentName className, IBinder service) {
if (mContext != null) {
upnpService = (AndroidUpnpService) service;//本地设备服务,用于执行投屏命令
upnpService.getRegistry().addListener(deviceListRegistryListener);//搜索设备的回调
ThreadManager.execute(new Runnable() {
@Override
public void run() {
if (mContext != null && upnpService != null) {
upnpService.getControlPoint().search();//搜索相关设备
}
}
});
}
}

public void onServiceDisconnected(ComponentName className) {
upnpService = null;
}
};

public class DeviceListRegistryListener extends DefaultRegistryListener {

@Override
public void remoteDeviceRemoved(Registry registry, RemoteDevice device) {
if (device.getType().getNamespace().equals(“schemas-upnp-org”)
&& device.getType().getType().equals(“MediaRenderer”)) {
final DeviceItem dmrDisplay = new DeviceItem(device, device
.getDetails().getFriendlyName(),
device.getDisplayString(), “(REMOTE) ”
+ device.getType().getDisplayString());
dmrRemoved(dmrDisplay);
}
}

@Override
public void remoteDeviceAdded(Registry registry, RemoteDevice device) {
if (device.getType().getNamespace().equals(“schemas-upnp-org”)
&& device.getType().getType().equals(“MediaRenderer”)) {
final DeviceItem dmrDisplay = new DeviceItem(device, device
.getDetails().getFriendlyName(),
device.getDisplayString(), “(REMOTE) ”
+ device.getType().getDisplayString());
dmrAdded(dmrDisplay);
}
}

public void dmrAdded(final DeviceItem di) {
if (mTvDataList == null) {
mTvDataList = new ArrayList<>();
}
mTvDataList.add(di);
}

public void dmrRemoved(final DeviceItem di) {
if (mTvDataList != null && mTvDataList.contains(di)) {
mTvDataList.remove(di);
}
}
}
private void playToTv(DeviceItem deviceItem) {
String url = “网络视频链接”;
Service avtService = deviceItem.getDevice()
.findService(new UDAServiceType(“AVTransport”));
String metaData = TvUtil.pushMediaToRender(url, “video-item”, “DLNA测试视频”, “50:00”, “ggg”);
upnpService.getControlPoint().execute(new SetAVTransportURI(avtService, url, metaData) {
@Override
public void success(ActionInvocation invocation) {
super.success(invocation);
LogUtil.e(“playToTv”, “——-success”);
}

@Override
public void failure(ActionInvocation invocation, UpnpResponse operation, String defaultMsg) {
LogUtil.e(“playToTv”, “——-failure defaultMsg=” + defaultMsg);
}
});
}
当然上面的网络视频链接*好以*终的播放地址,不然会出现无法播放的情况.
————————————————

友情链接: SITEMAP | 旋风加速器官网 | 旋风软件中心 | textarea | 黑洞加速器 | jiaohess | 老王加速器 | 烧饼哥加速器 | 小蓝鸟 | tiktok加速器 | 旋风加速度器 | 旋风加速 | quickq加速器 | 飞驰加速器 | 飞鸟加速器 | 狗急加速器 | hammer加速器 | trafficace | 原子加速器 | 葫芦加速器 | 麦旋风 | 油管加速器 | anycastly | INS加速器 | INS加速器免费版 | 免费vqn加速外网 | 旋风加速器 | 快橙加速器 | 啊哈加速器 | 迷雾通 | 优途加速器 | 海外播 | 坚果加速器 | 海外vqn加速 | 蘑菇加速器 | 毛豆加速器 | 接码平台 | 接码S | 西柚加速器 | 快柠檬加速器 | 黑洞加速 | falemon | 快橙加速器 | anycast加速器 | ibaidu | moneytreeblog | 坚果加速器 | 派币加速器 | 飞鸟加速器 | 毛豆APP | PIKPAK | 安卓vqn免费 | 一元机场加速器 | 一元机场 | 老王加速器 | 黑洞加速器 | 白石山 | 小牛加速器 | 黑洞加速 | 迷雾通官网 | 迷雾通 | 迷雾通加速器 | 十大免费加速神器 | 猎豹加速器 | 蚂蚁加速器 | 坚果加速器 | 黑洞加速 | 银河加速器 | 猎豹加速器 | 海鸥加速器 | 芒果加速器 | 小牛加速器 | 极光加速器 | 黑洞加速 | movabletype中文网 | 猎豹加速器官网 | 烧饼哥加速器官网 | 旋风加速器度器 | 哔咔漫画 | PicACG | 雷霆加速