GVKun编程网logo

Android手机运行图形界面的LINUX环境(安卓运行linux图形界面)

9

本文将为您提供关于Android手机运行图形界面的LINUX环境的详细介绍,我们还将为您解释安卓运行linux图形界面的相关知识,同时,我们还将为您提供关于AndroidApp界面的ListView布

本文将为您提供关于Android手机运行图形界面的LINUX环境的详细介绍,我们还将为您解释安卓运行linux图形界面的相关知识,同时,我们还将为您提供关于Android App界面的ListView布局实战演练、Android Studio环境在真手机运行app项目的详细方法、Android Wear将数据发送到Android手机,但手机似乎永远不会收到它、Android 开发之获取手机运行时间的实用信息。

本文目录一览:

Android手机运行图形界面的LINUX环境(安卓运行linux图形界面)

Android手机运行图形界面的LINUX环境(安卓运行linux图形界面)

刚开始在我废弃在Android手机上运行 spring boot 我已经惊呆了。
文章见:
《树莓派?云服务器?小主机?旧手机使用Termux安卓手机中跑Java跑spring boot不香吗?》

然后我就想在折腾折腾。看看能不能在android手机上跑图形界面的linux系统。还真行,而且很流畅。
简单的方法:
http://www.aidlearning.net/
下载app直接就搞定了,不用你折腾。各种开发环境都集成好了XFCE,vscode ,python,java 还有一个Chrome。

基于Termux (折腾)

官方文档写的非常详细了,我按照官方文档实测确实可以。
https://wiki.termux.com/wiki/Graphical_Environment
大致流程:

  • 1 安装X11 Repository
  • 2 配置VNC
  • 3 使用VNC Viewer 连接

效果

我测试的时候忘记截图了,图来自上面的文章,直接引用过来。个人感觉已经非常强大了。

手机上效果

在这里插入图片描述

FluxBox

在这里插入图片描述

OpenBox

在这里插入图片描述

Desktop environment (XFCE)

在这里插入图片描述

个人感觉真的很强大了,FluxBox和OpenBox 我都运行过啦按照上面这篇文章来就好了,如果遇到问题文章下面评论留言。就在我要测试 XFCE的时候我发现更简单的实现(aidlearning),就没有测试,下文会说。

测试OpenBox的时候最到了一个小坑,安装软件报错。还来发现我忘记执行:

pkg upgrade

所以在安装软件之前一定要执行一下这条命令pkg upgrade.

Aid learning(简单)

在测试 在Termux安装桌面环境XFCE的时候,偶然中发现的Aid learning。
http://www.aidlearning.net/
我只能说这个大佬太强了,玩到了极致。
非常简单,直接安装这个app就好了,所有内容都配置好了。

效果

多惊艳直接看图好了。

在这里插入图片描述


在这里插入图片描述

和PC一起协同开发

只需要一个网址,你就可以把Aid平台通过wifi投影到你的电脑端,在电脑端大屏上用Aid内置的环境继续学习和开发.

在这里插入图片描述

VSCode

在这里插入图片描述

个人感受:手机变身linux电脑

在这里插入图片描述


在这里插入图片描述

感谢作者把这个app 集成做到了极致,小白也能在android上跑图形化的Linux喽。

第一眼被惊艳到了,玩了一会我就感觉到了,这app酷似mac风格的界面是用html开发的。

有可玩性,实际真在手机上搞开发还是不太方便的,如果有蓝牙键盘可能会好一些。对于没有电脑,或者上班,出差路上没有电脑,用来学习linux,学习python,学习java 真的不错。

手机在手天下我有的时代快要来了!很期待未来的发展。

参考文档

https://wiki.termux.com/wiki/Graphical_Environment

Android App界面的ListView布局实战演练

Android App界面的ListView布局实战演练

一、继承listActivity、使用arrayAdapter
使用ListView和arrayAdapter布局,是ListView布局中最为简单的一种,首先我们会建立一个组件用来显示数据,例如main.xml

<?xml version="1.0" encoding="utf-8"?> 
<!-- 主界面本身就是一个显示组件 --> 
<TextView xmlns:android="http://schemas.android.com/apk/res/android" 
  android:layout_width="fill_parent" 
  android:layout_height="fill_parent" 
  android:padding="10dp" 
  android:textSize="16sp" 
    > 
 
</TextView> 

Activity代码如下

package cn.com.android.grid; 
 
import android.app.ListActivity; 
import android.os.Bundle; 
import android.widget.ArrayAdapter; 
 
public class listViewTest extends ListActivity { 
 
  @Override 
  protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    String data[] = getData(); 
    ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this,R.layout.main,data); 
    this.setlistadapter(arrayAdapter);// ArrayAdapter 继承自baseAdapter,baseAdapter又继承自listadapter 
     
     
  } 
 
  /** 
   * @author chenzheng_java 
   * @description 获取一个数组列表 
   */ 
  private String[] getData(){ 
    String[] data = new String[100]; 
    for (int i = 0; i < 100; i++) { 
      data[i] = "列表项" + i; 
    } 
    return data; 
     
  } 
   
} 

如果这里activity不想继承ListActivity,那么我们可以这样编写

package cn.com.android.grid; 
 
import android.app.Activity; 
import android.os.Bundle; 
import android.widget.ArrayAdapter; 
import android.widget.ListView; 
 
public class ListViewTest2 extends Activity { 
 
  @Override 
  protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
     
    ListView listView = new ListView(this);  
    listView.setAdapter(new ArrayAdapter<String>(this,getData()));  
    setContentView(listView);  
 
  } 
  /** 
   * @author chenzheng_java 
   * @description 获取一个数组列表 
   */ 
  private String[] getData(){ 
    String[] data = new String[100]; 
    for (int i = 0; i < 100; i++) { 
      data[i] = "列表项" + i; 
    } 
    return data; 
     
  } 
   
} 

废话连篇:
两种实现办法写的代码差距很大,有很多初学者可能很晕。不过不要紧,我们一起看下ListActivity到底是怎么实现的。
代码摘录如下

public class ListActivity extends Activity { 
  /** 
   * This field should be made private,so it is hidden from the SDK. 
   * {@hide} 
   */ 
  protected listadapter mAdapter; 
  /** 
   * This field should be made private,so it is hidden from the SDK. 
   * {@hide} 
   */ 
  protected ListView mList; 

我们看到了,实际上当我们继承ListActivity时,实际上里面已经有一个从ListActivity中继承的listview了,所以千万别以为差距很大,本质上,实现的步骤是一摸一样的。你可以认为,android给你提供了一个免费的工具类。没什么稀奇的。

步骤上,还是三大步:
第一步:准备布局文件main.xml
第二步:获取数据 getData()
第三步:绑定数据源setlistadapter();

二、用simpleAdapter绑定数据
最终效果图

2016412155948032.gif (361×531)

目录结构

2016412160014542.gif (260×410)

main.xml主布局文件,代码

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  android:orientation="vertical" 
  android:layout_width="fill_parent" 
  android:layout_height="fill_parent" 
  > 
<TextView  
  android:layout_width="fill_parent"  
  android:layout_height="wrap_content"  
  android:text="@string/hello" 
/> 
  <LinearLayout 
  android:layout_width="wrap_content" 
  android:layout_height="wrap_content" > 
  <TextView 
    android:text="@string/name" 
    android:gravity="center" 
     android:layout_width="150px" 
    android:layout_height="wrap_content" 
  /> 
   
  <TextView 
    android:text="@string/age" 
    android:gravity="center" 
     android:layout_width="170px" 
    android:layout_height="wrap_content" 
  /> 
   
  </LinearLayout> 
  <ListView 
  android:id="@+id/listView" 
  android:layout_width="wrap_content" 
  android:layout_height="wrap_content" 
  /> 
      
</LinearLayout> 

user.xml组件布局文件代码

<?xml version="1.0" encoding="utf-8"?> 
<!-- 创建存放一行数据的组件 --> 
<TableLayout 
 xmlns:android="http://schemas.android.com/apk/res/android" 
 android:layout_width="fill_parent" 
 android:layout_height="wrap_content"> 
 <TableRow> 
  
 <ImageView 
  android:id="@+id/image" 
  android:layout_width="50px"   
  android:layout_height="50px"  
 ></ImageView> 
  
 <TextView 
  android:id="@+id/userName" 
  android:gravity="center" 
  android:layout_height="wrap_content" 
  android:layout_width="150px" 
 ></TextView> 
  
 <TextView 
  android:id="@+id/userAge" 
  android:gravity="center" 
  android:layout_height="wrap_content" 
  android:layout_width="170px" 
 ></TextView> 
  
 </TableRow> 
</TableLayout> 

主Activity,listView.java代码

package cn.com.android.listView; 
 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 
 
import android.app.Activity; 
import android.os.Bundle; 
import android.widget.ListView; 
import android.widget.SimpleAdapter; 
 
public class listView extends Activity { 
  @Override 
  public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 
    ListView listView = (ListView) findViewById(R.id.listView); 
    /* 参数一多,有些人就头晕了。这里解说下,各个参数的意思。 
     * 第一个参数 this 代表的是当前上下文,可以理解为你当前所处的activity 
     * 第二个参数 getData() 一个包含了数据的List,注意这个List里存放的必须是map对象。simpleAdapter中的限制是这样的List<? extends Map<String,?>> data 
     * 第三个参数 R.layout.user 展示信息的组件 
     * 第四个参数 一个string数组,数组内存放的是你存放数据的map里面的key。 
     * 第五个参数:一个int数组,数组内存放的是你展示信息组件中,每个数据的具体展示位置,与第四个参数一一对应 
     * */ 
    SimpleAdapter adapter = new SimpleAdapter(this,getData(),R.layout.user,new String[]{"image","userName","userAge"},new int[]{R.id.image,R.id.userName,R.id.userAge}); 
    listView.setAdapter(adapter); 
     
  } 

  /** 
   * @author chenzheng_java 
   * @description 准备一些测试数据 
   * @return 一个包含了数据信息的hashMap集合 
   */ 
  private ArrayList<HashMap<String,Object>> getData(){ 
    ArrayList<HashMap<String,Object>> arrayList = new ArrayList<HashMap<String,Object>>(); 
    for(int i=0;i<10;i++){ 
      HashMap<String,Object> tempHashMap = new HashMap<String,Object>(); 
      tempHashMap.put("image",R.drawable.icon); 
      tempHashMap.put("userName","用户"+i); 
      tempHashMap.put("userAge",30-i); 
      arrayList.add(tempHashMap); 
       
    } 
     
     
    return arrayList; 
     
  } 
   
   
} 

strings.xml代码

<?xml version="1.0" encoding="utf-8"?> 
<resources> 
  <string name="hello">布局列表展示</string> 
  <string name="app_name">列表布局</string> 
  <string name="name">姓名</string> 
  <string name="age">年龄</string> 
</resources> 

废话连绵:
我们一起看看结构,一个主布局文件,一个组件布局文件,一个Activity类。
依旧分为三步:
第一步:定义布局文件,设计UI,包括寻找合适的图片了等等……
第二步:获取数据。这里用的是simpleAdapter,所以要求数据必须固定格式的;
第三步:绑定数据源。
然后,我们就可以看到我们想要的结果了。

三、有按钮的ListView
下面我们是要看使用自定义的Adapter绑定数据、通过contextView.setTag绑定数据的方式,最终结果图:

2016412160121866.gif (321×477)

代码结构示意图

2016412160139120.gif (268×525)

vlist2.xml代码:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout 
 xmlns:android="http://schemas.android.com/apk/res/android" 
 android:layout_width="fill_parent" 
 android:layout_height="fill_parent"> 
  
 <ImageView 
  android:id="@+id/image" 
  android:layout_width="wrap_content" 
  android:layout_height="wrap_content" 
  android:layout_margin="5px" 
 /> 
  
 <LinearLayout 
  android:layout_width="wrap_content" 
  android:layout_height="wrap_content" 
  android:orientation="vertical" 
 > 
  <TextView 
    android:id="@+id/title" 
    android:layout_width="wrap_content"  
    android:layout_height="wrap_content"  
    android:textColor="#FFFFFFFF"  
    android:textSize="22px"  
     
  /> 
  <TextView 
    android:id="@+id/info" 
    android:layout_width="wrap_content"  
    android:layout_height="wrap_content"  
    android:textColor="#FFFFFFFF"  
    android:textSize="13px"  
     
  /> 
 </LinearLayout> 
  
 <Button 
  android:id="@+id/view_btn" 
  android:layout_width="wrap_content"  
  android:layout_height="wrap_content" 
  android:text="click me" 
  android:gravity="center" 
 /> 
  
  
</LinearLayout> 

listView3.java代码

package cn.com.android2.listview; 
 
import java.util.ArrayList; 
import java.util.HashMap; 
 
import android.app.ListActivity; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.View; 
import android.widget.ListView; 
 
public class listView3 extends ListActivity { 
  @Override 
  public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    // 获取虚拟的数据,数据的格式有严格的要求哦 
    ArrayList<HashMap<String,Object>> data = getData(); 
    //模仿SimpleAdapter实现的自己的adapter 
    MyAdapter adapter = new MyAdapter(this,data); 
     
    /** 
     * 有些人很迷糊,我们都知道vlist2.xml相当于存储一行数据的组件布局,我们在前边的代码中,都是有一个主布局文件main.xml的, 
     * 组件布局文件是放在主布局文件上显示的,一般代码中都是通过setContentView()来指定主布局文件的。为何这里根本就没有用到 
     * ,但是listView还能有一个界面来呈现呢。 
     * 让我们看看setlistadapter在ListActivity中的实现, 
     * public void setlistadapter(listadapter adapter) { 
      synchronized (this) { 
      ensureList(); 
      mAdapter = adapter; 
      mList.setAdapter(adapter); 
    } 
  } 
  里面调用了一个ensureList方法,我们再来看看这个方法: 
   private void ensureList() { 
    if (mList != null) { 
      return; 
    } 
    setContentView(com.android.internal.R.layout.list_content); 
 
  } 
  现在看到了,这里有个 setContentView方法,里面设置了我们的组件在一个android自己提供的界面上显示。 
  原来,我们的理论还是适用的,只不过ListActivity给我进行了隐藏实现。 
     */ 
    setlistadapter(adapter); 
 
  } 
 
  /** 
   * @author chenzheng_java 
   * @description 准备一些测试数据 
   * @return 一个包含了数据信息的hashMap集合 
   */ 
  private ArrayList<HashMap<String,R.drawable.icon); 
      tempHashMap.put("title","标题"+i); 
      tempHashMap.put("info","描述性信息"); 
      arrayList.add(tempHashMap); 
    } 
    return arrayList; 
  } 
 
  @Override 
  protected void onListItemClick(ListView l,View v,int position,long id) { 
     
    Log.i("输出信息",v.toString() ); 
  } 
 
} 

zujian.java

package cn.com.android2.listview; 
 
import android.widget.Button; 
import android.widget.ImageView; 
import android.widget.TextView; 
 
public final class ZuJian { 
 
  public ImageView imageView; 
  public TextView titleView; 
  public TextView infoView; 
  public Button button; 
   
   
} 

MyAdapter.java

package cn.com.android2.listview; 
 
import java.util.ArrayList; 
import java.util.HashMap; 
 
import android.app.AlertDialog; 
import android.content.Context; 
import android.content.DialogInterface; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.view.View.OnClickListener; 
import android.widget.BaseAdapter; 
import android.widget.Button; 
import android.widget.ImageView; 
import android.widget.TextView; 
/** 
 * @author chenzheng_java 
 * @description 该类的部分实现模仿了SimpleAdapter 
 */ 
public class MyAdapter extends BaseAdapter { 
   
  private ArrayList<HashMap<String,Object>> data; 
  /** 
   * LayoutInflater 类是代码实现中获取布局文件的主要形式 
   *LayoutInflater layoutInflater = LayoutInflater.from(context); 
   *View convertView = layoutInflater.inflate(); 
   *LayoutInflater的使用,在实际开发种LayoutInflater这个类还是非常有用的,它的作用类似于 findViewById(),不同点是LayoutInflater是用来找layout下xml布局文件,并且实例化! 
  而findViewById()是找具体xml下的具体 widget控件(如:Button,TextView等)。 
   */ 
  private LayoutInflater layoutInflater; 
  private Context context; 
   
   
  public MyAdapter(Context context,ArrayList<HashMap<String,Object>> data) { 
     
    this.context = context; 
    this.data = data; 
    this.layoutInflater = LayoutInflater.from(context); 
  } 
 
  /** 
   *获取列数 
   */ 
  public int getCount() { 
    return data.size(); 
  } 
  /** 
   *获取某一位置的数据 
   */ 
  public Object getItem(int position) { 
    return data.get(position); 
  } 
  /** 
   *获取唯一标识 
   */ 
  public long getItemId(int position) { 
    return position; 
  } 
 
  /** 
   * android绘制每一列的时候,都会调用这个方法 
   */ 
  public View getView(int position,View convertView,ViewGroup parent) { 
    ZuJian zuJian = null; 
    if(convertView==null){ 
      zuJian = new ZuJian(); 
      // 获取组件布局 
      convertView = layoutInflater.inflate(R.layout.vlist2,null); 
      zuJian.imageView = (ImageView) convertView.findViewById(R.id.image); 
      zuJian.titleView = (TextView) convertView.findViewById(R.id.title); 
      zuJian.infoView = (TextView) convertView.findViewById(R.id.info); 
      zuJian.button = (Button) convertView.findViewById(R.id.view_btn); 
      // 这里要注意,是使用的tag来存储数据的。 
      convertView.setTag(zuJian); 
    } 
    else { 
      zuJian = (ZuJian) convertView.getTag(); 
    } 
    // 绑定数据、以及事件触发 
    zuJian.imageView.setBackgroundResource((Integer) data.get(position).get("image")); 
    zuJian.titleView.setText((String)data.get(position).get("title")); 
    zuJian.infoView.setText((String)data.get(position).get("info")); 
    zuJian.button.setonClickListener(new OnClickListener(){ 
 
      public void onClick(View v) { 
        showInfo(); 
      } 
       
    }); 
    return convertView; 
  } 
 
  /** 
   *当用户点击按钮时触发的事件,会弹出一个确认对话框 
   */ 
   public void showInfo(){  
 
         new AlertDialog.Builder(context)  
 
         .setTitle("我的listview")  
 
        .setMessage("介绍...")  
 
        .setPositiveButton("确定",new DialogInterface.OnClickListener() {  
 
        public void onClick(DialogInterface dialog,int which) {  
 
           }  
 
         })  
 
        .show();  
 
           
 
      }  
 
} 

废话连篇:

代码中的注释已经解释的很清楚了,这里再次强调一遍,三步骤
第一步:准备主布局文件、组件布局文件等
第二步:获取并整理数据
第三部:绑定数据,这里我们是通过自己编写adapter来完成的。

listView在开始绘制的时候,系统首先调用getCount()函数,根据他的返回值得到listView的长度,然后根据这个长度,调用getView()逐一绘制每一行。
如果你的getCount()返回值是0的话,列表将不显示同样return 1,就只显示一行。
系统显示列表时,首先实例化一个适配器(这里将实例化自定义的适配器)。当手动完成适配时,必须手动映射数据,这需要重写getView()方法。系统在绘制列表的每一行的时候将调用此方法。
getView()有三个参数,position表示将显示的是第几行,covertView是从布局文件中inflate来的布局。我们用LayoutInflater的方法将定义好的vlist2.xml文件提取成View实例用来显示。然后将xml文件中的各个组件实例化(简单的findViewById()方法)。
这样便可以将数据对应到各个组件上了。但是按钮为了响应点击事件,需要为它添加点击监听器,这样就能捕获点击事件。至此一个自定义的listView就完成了,现在让我们回过头从新审视这个过程。系统要绘制ListView了,他首先获得要绘制的这个列表的长度,然后开始绘制第一行,怎么绘制呢?调用getView()函数。在这个函数里面首先获得一个View(实际上是一个ViewGroup),然后再实例并设置各个组件,显示之。好了,绘制完这一行了。那 再绘制下一行,直到绘完为止。在实际的运行过程中会发现listView的每一行没有焦点了,这是因为Button抢夺了listView的焦点,只要布局文件中将Button设置为没有焦点就OK了。

Android Studio环境在真手机运行app项目的详细方法

Android Studio环境在真手机运行app项目的详细方法

android studio中,在真机运行app项目,步骤繁琐,新手不易上手。php小编小新将一一介绍真机运行app项目的详细方法,包括所需工具、开启usb调试、连接真机、安装apk等关键步骤,帮助大家轻松解决真机运行app项目的问题。

要想将Android Studio的开发的Android的项目部署到手机进行调式的话,就需使用数据把电脑与手机进行连接。

Android Studio环境在真手机运行app项目的详细方法

然后打开Android Studio的开发软件,进入到当前的项目中,选中一个项目。

Android Studio环境在真手机运行app项目的详细方法

点击运行菜单中一个运行按钮,如果没有选中项目,运行图标左侧位置,可以再次选择项目需要部署项目。

弹出choose device选项框中,可以看到choose a running device的真机列表,选中一个已连接真机,然后点击【OK】。

Android Studio环境在真手机运行app项目的详细方法

选择底部位置中的Android的按钮,就弹出一个为logcat的信息,和devices中真机和虚拟机的列表。

Android Studio环境在真手机运行app项目的详细方法

通过安装完成之后会直接在手机中打开应用的界面中,就能通过Android Studio进行调式项目app。

Android Studio环境在真手机运行app项目的详细方法

以上就是Android Studio环境在真手机运行app项目的详细方法的详细内容,更多请关注php中文网其它相关文章!

Android Wear将数据发送到Android手机,但手机似乎永远不会收到它

Android Wear将数据发送到Android手机,但手机似乎永远不会收到它

简短摘要:我正在尝试使用PutDataRequest和Googleapiclient将 Android Wear手表中的数据发送到Android手机.日志似乎表明数据已成功发送,但onDataChanged永远不会触发.我使用的是Android Studio 1.0.2.我没有使用任何模拟器,而是使用我自己的Android Wear手表 – 我已配对并通过手机上的Android Wear设备和Android Wear应用程序启用调试.在手机和Wear的AndroidManifest.xml上,我都包含了com.google.android.gms.version.

在Android手机(Android 4.4.4版本)上,我使用了一个侦听器服务,该服务通过AndroidManifest.xml绑定,并通过手机上的主要活动启动.从日志中,我可以确认在手机上成功创建了服务,但是没有收到任何数据(onDataChanged永远不会触发 – 准确地说).

<!-- Phone manifest,registers the listener -->
    <service android:name=".DataLayerListenerService" >
        <intent-filter>
            <action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
        </intent-filter>
    </service>

这是在手机上运行的监听服务:

public class DataLayerListenerService extends WearableListenerService {
    private static final String TAG = DataLayerListenerService.class.getName();
    private Googleapiclient mGoogleapiclient;

    private static final String WEaraBLE_DATA_PATH = "/audio";

    @Override
    public void onCreate() {
        // I can see this fires properly on the Android mobile phone
        Logger.d(TAG,"onCreate");
    }

    @Override
    public void onDataChanged(DataEventBuffer dataEvents) {
        // This never fires on the Android mobile phone,even though Wear says data was sent successfully
        Logger.d(TAG,"on change");
    }
}

在Wear设备上,我有一个主要活动,可以创建一个Google Api客户端.我使用UI按钮从音频生成输入(代码未显示),我知道这是因为日志记录正常工作.然后我尝试将这些数据从磨损设备发送到手机.在日志中,我看到“结果可用.状态:状态{statusCode = SUCCESS,resolution = null}”(我使用结果回调来跟踪).

public class MainActivity extends Activity implements
    Googleapiclient.ConnectionCallbacks,Googleapiclient.OnConnectionFailedListener {
    private static final String TAG = MainActivity.class.getName();
    private static final int SPEECH_REQUEST_CODE = 1;

    private static final int RECORDER_SAMPLERATE = 44100;
    private static final int RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_STEREO;
    private static final int RECORDER_AUdio_ENCODING = AudioFormat.ENCODING_PCM_16BIT;

    private TextView mTextView;
    private AudioRecord recorder;
    private int bufferSize = 0;
    private Thread recordingThread = null;
    private Googleapiclient mGoogleapiclient;
    private volatile boolean isRecording;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.d(TAG,"Creating MainActivity");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
        stub.setonLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
            @Override
            public void onLayoutInflated(WatchViewStub stub) {
                mTextView = (TextView) stub.findViewById(R.id.text);
            }
        });

        mGoogleapiclient = new Googleapiclient.Builder(this)
                .addApi(Wearable.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();
    }

    // Connect to the data layer when the Activity starts
    @Override
    protected void onStart() {
        super.onStart();
        mGoogleapiclient.connect();
    }

    protected void onResume() {
        if (null != mGoogleapiclient && !mGoogleapiclient.isConnected()) {
            mGoogleapiclient.connect();
        }
        super.onResume();
    }

    @Override
    protected void onStop() {
        if (null != mGoogleapiclient && mGoogleapiclient.isConnected()) {
            mGoogleapiclient.disconnect();
        }
        super.onStop();
    }

    // Placeholders for required connection callbacks
    @Override
    public void onConnectionSuspended(int cause) {
        Log.d(TAG,"Connection suspended");
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        Log.d(TAG,"Connection Failed");
    }

    @Override
    public void onConnected(Bundle connectionHint) {
        Log.d(TAG,"Connected successfully");
    }

    // This is invoked from the UI,via a helper method not shown. Logs show the method is invoked fine.
    private void processRawAudioData() {
        byte data[] = new byte[bufferSize];
        int read = 0;
        while(isRecording) {
            read = recorder.read(data,bufferSize);

            if(AudioRecord.ERROR_INVALID_OPERATION != read) {
                Log.d(TAG,"Successfully read " + data.length + " bytes of audio");
                Log.d(TAG,"Initial ten bytes: " + data[0] + data[1] + data[2] + data[3]
                    + data[4] + data[5] + data[6] + data[7] + data[8] + data[9] + data[10]);

                Asset myAsset = Asset.createFromBytes(data);
                PutDataRequest request = PutDataRequest.create("/audio");
                // might need to change time each time for other end to see change.
                request.putAsset("profileImage",myAsset);
                PendingResult<DataApi.DataItemResult> result =
                    Wearable.DataApi.putDataItem(mGoogleapiclient,request);
                result.setResultCallback(new ResultCallback<DataApi.DataItemResult>() {
                    @Override
                    public void onResult(DataApi.DataItemResult dataItemResult) {
                     // LOGS SHOW STATUS "MainActivity﹕ result available. Status: Status{statusCode=SUCCESS,resolution=null}"   
                     Log.d(TAG,"result available. Status: " + dataItemResult.getStatus());
                    }
                });
            }
        }
    }
}

解决方法

为了让WearableListenerService触发’onDataChanged’事件,主应用程序和可穿戴应用程序中的applicationId必须匹配(build.gradle文件).

另外,你不能发送静态数据,数据必须改变.这意味着PutDataMapRequest对象中的数据必须更改.

Android 开发之获取手机运行时间

Android 开发之获取手机运行时间

前言

昨天我碰到一个问题,需要判断两次的时间,我当时的第一反应是用 System.currentTimeMillis () 来判断,最后发现这样会有一个 BUG,那就是用户如果手动修改时间,那就全乱套了,于是我想有没有一个时间是只增加不减少,并且用户是不能修改的?一查,发现还真有,主要和 SystemClock 有关,接下来对这个类进行学习。

SystemClock

三种时钟都是有效的,它们不应该被混淆:

  1. System.currentTimeMillis() 是一个标准的 “墙” 时钟 (时间和日期),表示从纪元到现在的毫秒数。该墙时钟能够被用户或电话网络 (见 setCurrentTimeMillis (long)) 设置,所以该时间可能会向前或向后不可预知地跳越。该时钟应该仅仅被使用在当现实世界对应的日期和时间非常重要的情况下,比如日历或闹钟应用程序。而间隔时间和经历时间的测算应该使用不同的时钟。如果你使用 System.currentTimeMillis (),当时间变化时时可以考虑监听 ACTION 为 ACTION_TIME_TICK、ACTION_TIME_CHANGED 和 ACTION_TIMEZONE_CHANGED 的广播。

  2. uptimeMillis() 表示自系统启动时开始计时,以毫秒为单位。返回的是从系统启动到现在这个过程中的处于非休眠期的时间。当系统进入深度睡眠时 (CPU 关闭,设备变黑,等待外部输入装置) 该时钟会停止。但是该时钟不会被时钟调整、闲置或其他节能机制所影响。这是大多数间隔时间的基本点,例如 Thread.sleep (millls)、Object.wait (millis) 和 System.nanoTime ()。该时钟被保证是单调的,适用于检测不包含休眠的间隔时间的情况。大多数接受一个时间戳值的方法认为是使用了 uptimeMillis () 时钟。

  3. elapsedRealtime() 和 elapsedRealtimeNanos() 返回系统启动到现在的时间,包含设备深度休眠的时间。该时钟被确保单调,即使 CPU 在省电模式下,该时间也会继续计时。该时钟可以被使用在测量时间间隔时系统可能睡眠的时间段。

这有一些机制为了控制定时事件的:

  1. 标准的功能 Thread.sleep(millis)Object.wait(millis) 都总是合适的。这是功能使用 uptimeMillis() 时钟;如果该设备进入睡眠,剩余的时间将被推迟直到系统唤醒。这些同步功能可能被中断伴随 Thread.interrupt() 方法,并且你必须处理 InterruptedException 异常。

  2. SystemClock.sleep(millis) 是一种实用工具函数变化类似于 Thread.sleep(millis),但是它忽视了 InterruptedException 异常。使用该函数产生的延迟如果你不使用 Thread.interrupt(),因为它会保存线程的中断状态。

  3. 处理程序类可以安排在绝对或相对时间异步回调。处理器类对象也使用 uptimeMillis() 时钟,并且需要一个 eventloop(正常呈现在任何一个 GUI 应用程序上)。该 AlarmManager 可以触发一次或重复事件去发生即使在深睡眠或你的应用程序没有运行。事件可能有计划的发生伴随你的 currentTimeMillis()(RTC) 机会或 elapsedRealtime()(ELAPSED_REALTIME),并且引起一个意图广播当它们发生时。

有几种机制可以控制事件发生的时间:

  1. 对标准的方法比如 Thread.sleep(millis) 和 Object.wait(millis) 都是有效的,这些方法使用的是 uptimeMillis () 时钟,如果设备进入深度休眠,剩余的时间将被推迟直到系统唤醒。这些同步方法可能被 Thread.interrupt () 中断,你必须处理 InterruptedException 异常。

  2. SystemClock.sleep(millis) 是一个类似于 Thread.sleep(millis) 的实用方法,但是它忽略 InterruptedException 异常(其实就是使用 Thread.sleep,不过对异常进行了处理)。使用该函数会产生延迟,如果你不使用 Thread.interrupt (),因为它会保存线程的中断状态。

  3. Handler 类可以在一个相对或者绝对的时间设置异步回调,Handler 对象也使用 uptimeMillis() 时钟,而且需要一个 loop (经常出现在 GUI 程序中)。

  4. AlarmManager 可以触发一次或重复事件,即使设备深度休眠或者应用程序没有运行。事件可以选择用 currentTimeMillis()(RTC) 或者 elapsedRealtime()(ELAPSED_REALTIME) 来设置时间,当事件发生会触发一个 Intent 广播。

  5. public 方法:

static long currentThreadTimeMillis () 返在当前线程运行的毫秒数。

static long elapsedRealtime () 返回系统启动到现在的毫秒数,包含休眠时间。

static long elapsedRealtimeNanos () 返回系统启动到现在的纳秒数,包含休眠时间。

static boolean setCurrentTimeMillis (long millis) 设置当前挂钟时间,以毫秒为单位。需要调用进程具有相应的权限。

static void sleep (long ms) 等待给定的时间(uptimeMillis)。和 Thread.sleep (millis) 类似,但是它不会抛出 InterruptedException 异常。事件被推迟到下一个中断操作。该方法直到指定的时间过去才返回。

static long uptimeMillis () 返回系统启动到现在的毫秒级时间,不包含休眠时间。(系统启动到现在的非休眠期时间)

我们今天的关于Android手机运行图形界面的LINUX环境安卓运行linux图形界面的分享就到这里,谢谢您的阅读,如果想了解更多关于Android App界面的ListView布局实战演练、Android Studio环境在真手机运行app项目的详细方法、Android Wear将数据发送到Android手机,但手机似乎永远不会收到它、Android 开发之获取手机运行时间的相关信息,可以在本站进行搜索。

本文标签: