当前位置:首页 > 芯闻号 > 充电吧
[导读]昨天正式开始 Android 编程学习与实践,由于 Android 模拟器在 WinXP 下一直未安装成功(见帖子: http://bbs.csdn.net/topics/390879802),所在将

昨天正式开始 Android 编程学习与实践,由于 Android 模拟器在 WinXP 下一直未安装成功(见帖子: http://bbs.csdn.net/topics/390879802),所在将闲置很久的 Android 手机: 联想 A750 找到用于调试。

A750 是 Android 版本是: 2.3.6,在手机 上打开 USB 调试功能后,就可以通过 USB 线与 PC 连接进行调试了。
调试的主要功能是 Socket 通讯,手机做为服务器端。先用 PC 做为客户端。后期的客户端是车机,车机的系统可能是 WinCE 或 Android。
开始之前,先了解了一下 Android 编程的基本知识(后附个人学习记录的知识点),然后学习了如下链接: http://www.cnblogs.com/lknlfy/archive/2012/03/04/2379628.html 关于 Socket 编程的知识。

其中 一个关键的知识点是线程与主进程之间的消息传递机制,主要是线程中的消息传递到主进程。例如:

mHandler.sendMessage(msg);



手机端代码如下(XML就不提供了,很简单,大家看图就知识的):
/*
 * 通过  WIFI 网络进行 Socket 通讯成功, 手机的 IP: 172.25.103.4(随个人网络环境变化)
 * 测试使用 360 随身 WIFI, PC 机的 IP: 172.25.103.1
 * */

package com.jia.leozhengfirstapp;


import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.ServerSocket;
import java.net.Socket;


import android.support.v7.app.ActionBarActivity;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.Toast;




public class MainActivity extends ActionBarActivity {


	private Socket clientSocket = null;
	private ServerSocket mServerSocket = null;


	private Handler mHandler = null;


	private AcceptThread mAcceptThread = null;
	private ReceiveThread mReceiveThread = null;
	private boolean stop = true;
	
	private TextView ipText;
	private TextView rcvText;
	private TextView ConnectStatusText;
	
    @SuppressLint("HandlerLeak")
	@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        ipText = (TextView)findViewById(R.id.textView1);
        rcvText = (TextView)findViewById(R.id.textView3);
        ConnectStatusText = (TextView)findViewById(R.id.textView4);
        
        ConnectStatusText.setText("连接状态: 未连接");
        
        // 消息处理
        mHandler = new Handler()
        {
            @Override
            public void handleMessage(Message msg)
            {
                switch(msg.what)
                {
                    case 0:
                    {
                    	String strAddress = (msg.obj).toString();
                        ipText.setText("IP地址: " + strAddress);
                        Log.v("Leo: IP: ", strAddress);
                        ConnectStatusText.setText("连接状态: 已连接");
                        // 显示客户端IP
                        // ipTextView.setText((msg.obj).toString());
                        // 使能发送按钮
                        // sendButton.setEnabled(true);
                        break;
                    }
                    case 1:
                    {
                    	String strRcv = (msg.obj).toString();
                        rcvText.setText("接收到数据: " + strRcv);
                        Log.v("Leo: Rcv: ", strRcv);
                        // 显示接收到的数据
                        // mTextView.setText((msg.obj).toString());
                        break;
                    }                 
                }                                           
                
            }
        };
        
        mAcceptThread = new AcceptThread();
        // 开启监听线程
        mAcceptThread.start();
    }




    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }


    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
    
    // 显示Toast函数
    private void displayToast(String s)
    {
        Toast.makeText(this, s, Toast.LENGTH_SHORT).show();
    }
    
    private class AcceptThread extends Thread
    {
        @Override
        public void run()
        {
            try {
                // 实例化ServerSocket对象并设置端口号为 12589
                mServerSocket = new ServerSocket(12589);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
            try {
                // 等待客户端的连接(阻塞)
                clientSocket = mServerSocket.accept();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
            mReceiveThread = new ReceiveThread(clientSocket);
            stop = false;
            // 开启接收线程
            mReceiveThread.start();
            
            Message msg = new Message();
            msg.what = 0;
            // 获取客户端IP
            msg.obj = clientSocket.getInetAddress().getHostAddress();
            // 发送消息
            mHandler.sendMessage(msg);
        }
    }




    private class ReceiveThread extends Thread
    {
        private InputStream mInputStream = null;
        private byte[] buf;  
        private String str = null;
        
        ReceiveThread(Socket s)
        {
            try {
                // 获得输入流
                this.mInputStream = s.getInputStream();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
        @Override
        public void run()
        {
            while(!stop)
            {
                this.buf = new byte[512];
                
                // 读取输入的数据(阻塞读)
                try {
                    this.mInputStream.read(buf);
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
                
                // 字符编码转换
                try {
                    this.str = new String(this.buf, "GB2312").trim();
                } catch (UnsupportedEncodingException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                
                Message msg = new Message();
                msg.what = 1;        
                msg.obj = this.str;
                // 发送消息
                mHandler.sendMessage(msg);
            }
        }
    }
}



1) 先通过 WIFI 进行 Socket 通讯
运行后,在手机上显示的未连接界面如下图:


在 PC 上运行类似于 SocketTool.exe 的工具,SocketTool.exe 的显示界面如下:


Socket 连接后,手机上显示的界面如下图:


2) 通过 USB 实现 PC 与手机的通讯
在 PC 上实现一个 Java 小应用,应用的主要代码如下:

try
{
    Runtime.getRuntime().exec("adb forward tcp:12581 tcp:12589");
}
catch (IOException e)
{
    e.printStackTrace();
}


Socket socket = null;
try
{
    InetAddress serverAddr = null;
    OutputStream outStream = null;
    byte[] msgBuffer = null;
    
    serverAddr = InetAddress.getByName("127.0.0.1");
    System.out.println("TCP 1" + "C: Connecting...");


    socket = new Socket(serverAddr, 12581);	// 12581 是 PC 的端口,已重定向到 Device 的 12589 端口
    
    String message = "PC ADB,send message";
    msgBuffer = message.getBytes("GB2312");
    
    outStream = socket.getOutputStream();
    outStream.write(msgBuffer);
    Thread.sleep(10000);
}
catch (UnknownHostException e1)
{
    System.out.println("TCP 2" + "ERROR: " + e1.toString());
}
catch (IOException e2)
{
    System.out.println("TCP 3" + "ERROR: " + e2.toString());
} catch (InterruptedException e3)
{
	// Thread.sleep(1000); 增加的异常处理
	e3.printStackTrace();
}
finally
{
    try
    {
        if (socket != null)
        {
            socket.close();		// 关闭时会导致接收到的数据被清空,所以延时 10 秒显示
        }
    }
    catch (IOException e)
    {
        System.out.println("TCP 4" + "ERROR: " + e.toString());
    }
}



运行后,在手机上显示的界面如下图:



以下是学习中记录的一些个人认为需要掌握的知识点,由于偶是从零开始学习的,所以有经难的朋友们可以直接忽略此部分:
Intent 用法:

Uri myUri = Uri.parse ("http://www.flashwing.net");
Intent openBrowserIntent = new Intent(Intent.ACTION_VIEW ,myUri);
startActivity(openBrowserIntent);


Intent openWelcomeActivityIntent= new Intent();
openWelcomeActivityIntent.setClass(AndroidStudy_TWO.this,Welcome.class);
startActivity(openWelcomeActivityIntent);


从源 Activity 中传递数据

// 数据写入 Intent
Intent openWelcomeActivityIntent= new Intent();
Bundle myBundelForName= new Bundle();
myBundelForName.putString("Key_Name",inName.getText().toString());
myBundelForName.putString("Key_Age",inAge.getText().toString());
openWelcomeActivityIntent.putExtras(myBundelForName);
openWelcomeActivityIntent.setClass(AndroidBundel.this,Welcome.class);
startActivity(openWelcomeActivityIntent);


// 从 Intent 中获取数据

Bundle myBundelForGetName= this.getIntent().getExtras();
String name=myBundelForGetName.getString("Key_Name");


从源请求 Activity 中通过一个 Intent 把一个服务请求传到目标 Activity 中

private Intent toNextIntent; //Intent 成员声明
toNextIntent = new Intent(); //Intent 定义
toNextIntent.setClass(TwoActivityME3.this,SecondActivity3.class);
// 设定开启的下一个 Activity
startActivityForResult(toNextIntent,REQUEST_ASK);
// 开启 Intent 时候 ,把请求码同时传递


在源请求 Activity 中等待 Intent 返回应答结果,通过重载 onActivityResult() 方法

@Override
protected void onActivityResult(int requestCode,int resultCode, Intent data)
{
  // TODO Auto-generated method stub
  super.onActivityResult(requestCode, resultCode, data);
  if (requestCode == REQUEST_ASK)
  {
    if (resultCode == RESULT_CANCELED)
    {
      setTitle( "Cancel****" );
    }
    else if (resultCode == RESULT_OK)
    {
      showBundle = data.getExtras(); // 从返回的 Intent 中获得 Bundle
      Name = showBundle.getString("myName"); // 从 bundle 中获得相应数据
      text.setText("the name get from the second layout:n" + Name);
    }
  }
}


* 第一个参数是你开启请求 Intent 时的对应请求码,可以自己定义。
* 第二个参数是目标 Activity 返回的验证结果码
* 第三个参数是目标 Activity 返回的 Intent

目标 Activity 中发送请求结果代码,连同源 Activity 请求的数据一同绑定到 Bundle 中通过 Intent 传回源请求 Activity 中

backIntent = new Intent();
stringBundle = new Bundle();
stringBundle.putString("myName",Name);
backIntent.putExtras(stringBundle);
setResult(RESULT_OK,backIntent); // 返回 Activity 结果码
finish();


使用服务进行音乐播放
Manifest.xml中的 Service 定义



Service 子类中的 Player

public void onStart(Intent intent, int startId) {
  super.onStart(intent, startId);
  player = MediaPlayer.create(this, R.raw.seven_days);
  player.start();
}
public void onDestroy() {
  super.onDestroy();
  player.stop();
}


Activity 中定义 的 Intent开启相应的

startService(new Intent("com.test.service.START_AUDIO_SERVICE"));
stopService(new Intent("com.test.service.START_AUDIO_SERVICE"));


DisplayMetrics displaysMetrics= new DisplayMetrics();
//DisplayMetrics 一个描述普通显示信息的结构,例如显示大小、密度、字体尺寸
getWindowManager().getDefaultDisplay().getMetrics(displaysMetrics);
//getManager() 获取显示定制窗口的管理器。
// 获取默认显示 Display 对象
// 通过 Display 对象的数据来初始化一个 DisplayMetrics 对象


标题栏/状态栏隐藏 ( 全屏 )
// 隐藏标题
requestWindowFeature(Window.FEATURE_NO_TITLE);
// 定义全屏参数
int flag = WindowManager.LayoutParams.FLAG_FULLSCREEN ;
// 获得窗口对象
Window myWindow = this.getWindow();
// 设置 Flag 标识
myWindow.setFlags(flag,flag);


Button 按下的处理:

press =(Button)findViewById(R.id.Click_Button);

(1)

press.setOnClickListener(new Button.OnClickListener()
{
  @Override
  public void onClick(View v)
  {
    // TODO Auto-generated method stub
  }
});


(2)

press.setOnClickListener(this);
@Override
public void onClick(View v)
{
  switch(v.getId()) /* 根据 ID 判断按钮事件 */
  {
    case R.id.Click_Button:
    {
    }
    break;
    default:
    break;
  }
}


Toast--Android 专属浮动小提示
(1) 显示文本: Toast.makeText
(2) 显示图像: 

/* 创建新 Toast 对象 */
Toast showImageToast= new Toast(this);
/* 创建新 ImageView 对象 */
ImageView imageView= new ImageView(this);
/* 从资源中获取图片 */
imageView.setImageResource(R.drawable. argon );
/* 设置 Toast 上的 View--(ImageView)*/
showImageToast.setView(imageView);
/* 设置 Toast 显示时间 */
showImageToast.setDuration(Toast. LENGTH_LONG );
/* 显示 Toast*/
showImageToast.show();



模拟器调试:

socket = new Socket("10.0.2.2", 12589);	// 如果用 localhost 不能成功连接



本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

罗德与施瓦茨与SmartViser携手开发了一种用于测试符合欧盟销售的智能手机和平板电脑的新Energy Efficiency Index(EEI)标签法规的解决方案。该解决方案的核心是R&S CMX500,这是...

关键字: 智能手机 Android iOS

(全球TMT2023年8月24日讯)2023年8月23日,时值实时3D引擎Unity在华设立合资公司Unity中国一周年之际,Unity中国正式推出Unity中国版引擎——团结引擎。Unity全球CEO John Ri...

关键字: UNITY CE Android 开发者

报告显示:全球电商 App 获客花费接近50亿美元 北京2023年8月23日 /美通社/ -- 全球营销衡量与体验管理平台 AppsFlyer 近日发布《2023 电商 App 营销现状报告》。尽管面临全球经...

关键字: APPS BSP iOS Android

数字机顶盒是一种数字技术下的多媒体娱乐中心,可以实现电视节目接收、播放、存储、网络应用等多种功能。随着科技的发展,数字机顶盒的设计方案也在不断进步和优化。本文将介绍数字机顶盒设计的几种实现方案。

关键字: 数字机顶盒 Android Linux

21ic 近日获悉,原小米 9 号创始员工李明在社交媒体平台公布了旗下首款产品乐天派桌面机器人,为全球首款 Android 桌面机器人,面向极客和发烧友的 AI + 机器人。据悉,李明两个月前宣布创业并进军 AI 领域,...

关键字: 小米 Android 桌面机器人 AI

尽管安装增长放缓,全球游戏 App 获客花费仍高达 267 亿美元 经济低迷导致 2023 游戏 App 营销优先考虑收入指标,用户增长次之 北京2023年3月9日 /美通社/ -- 今天,全球营销衡量与体验管理平台...

关键字: APPS iOS Android BSP

量子计算领域的新里程碑,来了! 谷歌科学家证明,通过增加量子比特的数量,就能降低量子计算的错误率。

关键字: 谷歌 Android Windows

「卫星通讯」正在被普及到每一台智能手机当中。普及的动机并非是消费市场的一个刚需,其实更像是将差异化的功能「抹平」成一个标配。时下,支持「卫星通讯」功能的智能手机只有苹果的 iPhone 14 系列与华为的 Mate 50...

关键字: 卫星通讯 Android 智能手机 iPhone

Android是Google开发的操作系统,支持多种指令集架构 (ISA),包括Arm和x86,多数使用Android的设备都采用Arm架构芯片组。新兴RISC-V架构是免费开放指令集架构,任何人都可用它设计芯片,且无需...

关键字: 谷歌 Android RISC-V架构

智能手机并非每年都取得重大进展,这导致越来越多的人将手机保留两年、三年或四年。不过,普通的 Android 手机能否在遇到问题之前使用那么久?

关键字: Android 安卓 谷歌 智能手机
关闭
关闭