Android中实现单选按钮的效果

 更新时间:2016年9月20日 19:56  点击:1607
单选按钮就是一组按钮只能选中其中的一个了,这个在html中有一个单选按钮组,那么在android开发中要如何来实现,具体的我们来看看。

我们经常在淘宝下单时,会选择尺寸,样式,在一排按钮里设置只能选中一个,我们知道按钮Button是不能唯一选中的,当我们点击一排按钮时我们会发现这一排全会被选择。下面我们就来看一下怎么样实现只选中一个按钮。

首先根据获取的数据动态生成一排按钮。

List<SizeEntity> sizeEntityList=productEntity.getSize();
if(sizeEntityList!=null&&sizeEntityList.size()>0) {
    for (int i = 0; i < sizeEntityList.size(); i++) {
       final SizeEntity size=sizeEntityList.get(i);
       final Button button = new Button(getContext());
       button.setId(i);
       button.setText(sizeEntityList.get(i).getName());
       button.setBackgroundResource(R.drawable.shape_round_corner_0_stroke_bg_grey);
       button.setTextSize(10);
       mSizeContent.addView(button, Math.min(1, mSizeContent.getChildCount()));
   }
}

下面来处理点击事件:

button.setOnClickListener(new OnClickListener() {
      @Override
      public void onClick(View view) {
          for (int j = 0; j < mSizeContent.getChildCount(); j++) {
               final Button mbutton = (Button) mSizeContent.getChildAt(j);
               if (button == mbutton) {
                  mbutton.setBackgroundResource(R.color.red);
                  mbutton.setTextColor(getResources().getColor(R.color.white));
               } else {
                  mbutton.setBackgroundResource(R.drawable.shape_round_corner_0_stroke_bg_grey);
                  mbutton.setTextColor(getResources().getColor(R.color.black));
                }
            }
 
       }
});

一个raid例子


xml文件

   <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"
    tools:context=".MainActivity"
    android:orientation="vertical">

    <TextView
        android:id="@+id/txt"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="您的性别为"/>
   
    <RadioGroup
        android:id="@+id/sex"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        <RadioButton
            android:id="@+id/male"
            android:text="男"/>
        <RadioButton
            android:id="@+id/female"
            android:text="女"/>
       
    </RadioGroup>

</LinearLayout>


java文件

public class MainActivity extends Activity {
private TextView txt=null;
private RadioGroup sex=null;
private RadioButton male=null;
private RadioButton female=null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.txt=(TextView) super.findViewById(R.id.txt);
this.sex=(RadioGroup) super.findViewById(R.id.sex);
this.male=(RadioButton) super.findViewById(R.id.male);
this.female=(RadioButton) super.findViewById(R.id.female);
this.sex.setOnCheckedChangeListener(new OnCheckedChangeListenerImp());
}
private class OnCheckedChangeListenerImp implements OnCheckedChangeListener{

public void onCheckedChanged(RadioGroup group, int checkedId) {
String temp=null;
if(MainActivity.this.male.getId()==checkedId){
temp="男";
}
else if(MainActivity.this.female.getId()==checkedId){
temp="女";
}
MainActivity.this.txt.setText("您的性别是"+temp);
}
}

}

在安卓开发应用中Live Wallpaper设定中加入AdMob广告是一个常事了,我们在下载的app中都会有广告了,这些广告是维护app收入来源的一个不错的方式了。

自从Android 2.1中加入了动态壁纸,一下子牛叉了很多啊,漂亮的壁纸层出不穷,看上去老土的Android手机总算也是可以炫一下了。

动态壁纸基础

制作方法,网上太多了,虽然基本都是抄的,其实都是从sample上发展出来的,我也把要点记一下,每次写新的都要把老的工程打开看,啥记性……

res/xml中指定动态壁纸的xml文件:

<?xml version="1.0" encoding="utf-8"?>
<wallpaper xmlns:android="http://schemas.android.com/apk/res/android"
 android:settingsActivity="xxx.yyy.LiveWallpaperSettings"
 android:thumbnail="@drawable/icon" />

这里是说明自己图标和设定Activity。
还有一个设定Activity的xml文件,就是普通的PreferenceScreen,省略。

创建WallpaperService的子类,需要再onCreateEngine方法中返回一个Engine,Engine中画画儿,就像用SurfaceView一样。


public class LiveWallpaper extends WallpaperService {
 public static final String SHARED_PREFS_NAME = "setting_file_name";
 @Override
 public void onCreate() {
  super.onCreate();
 }
 @Override
 public void onDestroy() {
  super.onDestroy();
 }
 @Override
 public Engine onCreateEngine() {
  return new TestPatternEngine();
 }
 class TestPatternEngine extends Engine implements
   SharedPreferences.OnSharedPreferenceChangeListener {
  private final Handler mHandler = new Handler();
  private final Runnable mDrawPattern = new Runnable() {
   public void run() {
    drawFrame();
   }
  };
  private boolean mVisible;
  private SharedPreferences mPreferences;
  TestPatternEngine() {
   mPreferences = LiveWallpaper.this.getSharedPreferences(
     SHARED_PREFS_NAME, 0);
   mPreferences.registerOnSharedPreferenceChangeListener(this);
   onSharedPreferenceChanged(mPreferences, null);
  }
  public void onSharedPreferenceChanged(SharedPreferences prefs,
    String key) {
  }
  @Override
  public void onCreate(SurfaceHolder surfaceHolder) {
   super.onCreate(surfaceHolder);
  }
  @Override
  public void onDestroy() {
   super.onDestroy();
   mHandler.removeCallbacks(mDrawPattern);
  }
  @Override
  public void onVisibilityChanged(boolean visible) {
   mVisible = visible;
   if (visible) {
    drawFrame();
   } else {
    mHandler.removeCallbacks(mDrawPattern);
   }
  }
  @Override
  public void onSurfaceChanged(SurfaceHolder holder, int format,
    int width, int height) {
   super.onSurfaceChanged(holder, format, width, height);
   drawFrame();
  }
  @Override
  public void onSurfaceCreated(SurfaceHolder holder) {
   super.onSurfaceCreated(holder);
  }
  @Override
  public void onSurfaceDestroyed(SurfaceHolder holder) {
   super.onSurfaceDestroyed(holder);
   mVisible = false;
   mHandler.removeCallbacks(mDrawPattern);
  }
  @Override
  public void onOffsetsChanged(float xOffset, float yOffset, float xStep,
    float yStep, int xPixels, int yPixels) {
   drawFrame();
  }
  void drawFrame() {
   final SurfaceHolder holder = getSurfaceHolder();
   Canvas c = null;
   try {
    c = holder.lockCanvas();
    if (c != null) {
     // draw something
    }
   } finally {
    if (c != null)
     holder.unlockCanvasAndPost(c);
   }
   mHandler.removeCallbacks(mDrawPattern);
   if (mVisible) {
    mHandler.postDelayed(mDrawPattern, 1000 / 25);
   }
  }
 }
}

还有设定Activity的实现:

public class LiveWallpaperSettings extends PreferenceActivity
    implements SharedPreferences.OnSharedPreferenceChangeListener {
    @Override
    protected void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        getPreferenceManager().setSharedPreferencesName(LiveWallpaper.SHARED_PREFS_NAME);
        addPreferencesFromResource(R.xml.livewallpaper_settings);
        getPreferenceManager().getSharedPreferences()
            .registerOnSharedPreferenceChangeListener(this);
    }
 
    @Override
    protected void onResume() {
        super.onResume();
    }
 
    @Override
    protected void onDestroy() {
        getPreferenceManager().getSharedPreferences()
            .unregisterOnSharedPreferenceChangeListener(this);
        super.onDestroy();
    }
 
    public void onSharedPreferenceChanged(
        SharedPreferences sharedPreferences, String key) {
    }
}

androidmanifest.xml中一定要加入的:


<service android:name=".LiveWallpaper" android:label="@string/app_name"  android:icon="@drawable/icon">
    <intent-filter>
        <action android:name="android.service.wallpaper.WallpaperService" />
    </intent-filter>
    <meta-data android:name="android.service.wallpaper" android:resource="@xml/livewallpaper" />
</service>
 
<activity android:label="@string/livewallpaper_settings"
   android:name=".LiveWallpaperSettings"
   android:theme="@android:style/Theme.Light.WallpaperSettings"
   android:exported="true"
   android:icon="@drawable/icon">
</activity>
 
<uses-sdk android:minSdkVersion="7" />
<uses-feature android:name="android.software.live_wallpaper" />

“uses-feature android:name=”android.software.live_wallpaper””这句话要慎用啊!Google的电子市场会认这句话,然后把有些可以用的机器过滤掉,比如俺的破机器,本来是不支持的,升级到2.1按说是可以用的。我看了市场上很多有名的动态壁纸,就没有加这句话~~
另外,如果想在动态壁纸中使用OpenGL ES,请参考这篇文章:Android中使用OpenGL ES的一二事。

加入AdMob广告

上面都是废话,我这次想说的主题是如何在壁纸设定界面里加入AdMob广告,好不容易做好的东西,总是要意思意思是吧,加个广告是没法的事情了。

不同于一般的Activity,直接加入AdMob是不行的,连个Layout都没有,而且直接加到壁纸上则非常糟糕,谁也不希望好好的背景上塞一个广告。所以一般动态壁纸的广告都加在设置界面里,这样还真有些不容易。

一般有两种方法,把Admob的adView当做一个Preference,直接加入xml就好。


public class AdmobPreference extends Preference {
 
    public AdmobPreference(Context context) {
        super(context, null);
    }
 
    public AdmobPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
 
    @Override
    protected View onCreateView(ViewGroup parent) {
        //override here to return the admob ad instead of a regular preference display
        LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        return inflater.inflate(R.layout.admob_preference, null);
    }
 
}

相对的admob_preference的配置:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/ad_layout"
    android:layout_width="fill_parent" android:layout_height="fill_parent">
 
    <com.google.ads.AdView
     xmlns:ads="http://schemas.android.com/apk/lib/com.google.ads"
  android:id="@+id/ad"
  android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        ads.adSize="BANNER"
        ads:adUnitId="a14e51ca560d266"
        ads:loadAdOnCreate="true"
         />
 
</LinearLayout>
Android AdView missing required XML attribute "adsize"

这里还是有些学问的,网上查一下会有无数的“AdView missing required XML attribute ‘adSize’”的问题,据说是4.1.0之后带来的问题,一定要这么写(将”http://schemas.android.com/apk/lib/com.google.ads”当做一个命名空间,而不是加入自己的程序中)才能不出错,至少大家是如此说的,可惜我不行,怎么写都有这个错,耗费了两个小时尝试了各种写法,还是不行啊!!最后还是写在代码里了:(

不过光这么写貌似还是不行,AdView周围还有留白,貌似是PreferenceActivity里的padding,去不掉,最后还是使用了Tab的方式:


public class SettingsTabActivity extends TabActivity {
 
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.table_layout);
 
        TabHost tabHost = getTabHost();  // The activity TabHost
        TabHost.TabSpec spec;  // Resusable TabSpec for each tab
        Intent intent;  // Reusable Intent for each tab
 
        // Create an Intent for the regular live wallpaper preferences activity
        intent = new Intent().setClass(this, LivePaperSettings.class);
 
        // Initialize a TabSpec and set the intent
        spec = tabHost.newTabSpec("TabTitle").setContent(intent);
        spec.setIndicator("TabTitle");
 
        tabHost.addTab(spec);
 
        tabHost.setCurrentTab(0);   
    }

对应的layout:

 

<?xml version="1.0" encoding="utf-8"?>
 
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:ads="http://schemas.android.com/apk/lib/com.google.ads"
 android:id="@android:id/tabhost" android:layout_width="fill_parent"
 android:layout_height="fill_parent">
 
 <LinearLayout android:orientation="vertical"
  android:id="@+id/main_layout"
  android:layout_width="fill_parent" android:layout_height="fill_parent">
 
  <com.google.ads.AdView android:id="@+id/ad"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   ads:backgroundColor="#000000"
   ads:primaryTextColor="#FFFFFF"
   ads:secondaryTextColor="#CCCCCC"
   ads.adSize="BANNER"
   ads:adUnitId="a14e51ca560d266"
   ads:loadAdOnCreate="true" />
 
  <TabWidget android:id="@android:id/tabs"
   android:layout_width="fill_parent" android:layout_height="1dp"
   android:visibility="invisible" />
 
  <FrameLayout android:id="@android:id/tabcontent"
   android:layout_width="fill_parent" android:layout_height="fill_parent"
   android:padding="1dp" />
 </LinearLayout>
</TabHost>
大概就是如此了。

对了还有一个浪费了我两个多小时的问题,对于已经按照的live wallpaper,你修改了setting的Activity,直接覆盖安装是没效果的,点配置还是出现以前的Activity,发现这一点之前,我做了不知几百次修改上传,都快整挂了,Google怎么考虑的?!

本教程的主要内容是运行两个Android模拟器,然后在这两个模拟器如何实现互相收发短信的功能,这个功能可以说是非常实现的,可以应用app短信实例中。

本文通过运行两个Android模拟器,介绍在Android中如何实现短信服务(SMS,short message service)的功能。通过这个例子,我想带给大家的是:更加熟悉之前介绍过的Android应用程序的概念及技术细节,且通过实例调度大家的兴趣。我之所以选择SMS为例子,主要原因是SMS已经非常成熟了,从中可以发掘更多的信息和技术细节,而且我相信大部分人发短信比打电话多。

1、温故知新

广播接收者:一个广播接收者是这样一个组件,它不做什么事,仅是接受广播公告并作出相应的反应。许多广播源自于系统代码,例如公告时区的改变、电池电量低、已采取图片、用户改变了语言偏好。应用程序也可以发起广播,例如为了他其他程序知道某些数据已经下载到设备且他们可以使用这些数据

BroadcastReceiver类:是接受sendBroadcast()发送的意图(intents)的基类。可以用Context.registerReceiver()动态地注册这个类的实例,或者通过AndroidManifest.xml中<receiver>标签静态发布。

广播接收者不显示一个用户界面。然而,它们启动一个活动去响应收到的信息,或者他们可能使用NotificationManager去通知用户。通知可以使用多种方式获得用户的注意——闪烁的背光、振动设备、播放声音等等。典型的是放在一个持久的图标在状态栏,用户可以打开获取信息。


2、准备工作:SMS涉及的主要类SmsManager

实现SMS主要用到SmsManager类,该类继承自java.lang.Object类,下面我们介绍一下该类的主要成员。

公有方法:

    ArrayList<String> divideMessage(String text)
    当短信超过SMS消息的最大长度时,将短信分割为几块。
    参数:text——初始的消息,不能为空
    返回值:有序的ArrayList<String>,可以重新组合为初始的消息
    static SmsManager getDefault()
    获取SmsManager的默认实例。
    返回值:SmsManager的默认实例
    void SendDataMessage(String destinationAddress, String scAddress, short destinationPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent)
    发送一个基于SMS的数据到指定的应用程序端口。
    参数:
    1)、destinationAddress——消息的目标地址
    2)、scAddress——服务中心的地址or为空使用当前默认的SMSC 3)destinationPort——消息的目标端口号
    4)、data——消息的主体,即消息要发送的数据
    5)、sentIntent——如果不为空,当消息成功发送或失败这个PendingIntent就广播。结果代码是Activity.RESULT_OK表示成功,或RESULT_ERROR_GENERIC_FAILURE、RESULT_ERROR_RADIO_OFF、RESULT_ERROR_NULL_PDU之一表示错误。对应RESULT_ERROR_GENERIC_FAILURE,sentIntent可能包括额外的“错误代码”包含一个无线电广播技术特定的值,通常只在修复故障时有用。
    每一个基于SMS的应用程序控制检测sentIntent。如果sentIntent是空,调用者将检测所有未知的应用程序,这将导致在检测的时候发送较小数量的SMS。
    6)、deliveryIntent——如果不为空,当消息成功传送到接收者这个PendingIntent就广播。
    异常:如果destinationAddress或data是空时,抛出IllegalArgumentException异常。
    void sendMultipartTextMessage(String destinationAddress, String scAddress, ArrayList<String> parts, ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent>  deliverIntents)
    发送一个基于SMS的多部分文本,调用者应用已经通过调用divideMessage(String text)将消息分割成正确的大小。
    参数:
    1)、destinationAddress——消息的目标地址
    2)、scAddress——服务中心的地址or为空使用当前默认的SMSC
    3)、parts——有序的ArrayList<String>,可以重新组合为初始的消息
    4)、sentIntents——跟SendDataMessage方法中一样,只不过这里的是一组PendingIntent
    5)、deliverIntents——跟SendDataMessage方法中一样,只不过这里的是一组PendingIntent
    异常:如果destinationAddress或data是空时,抛出IllegalArgumentException异常。
    void sendTextMessage(String destinationAddress, String scAddress, String text, PendingIntent sentIntent, PendingIntent deliveryIntent)
    发送一个基于SMS的文本。参数的意义和异常前面的已存在的一样,不再累述。

常量:

    public static final int RESULT_ERROR_GENERIC_FAILURE
    表示普通错误,值为1(0x00000001)
    public static final int RESULT_ERROR_NO_SERVICE
    表示服务当前不可用,值为4 (0x00000004)
    public static final int RESULT_ERROR_NULL_PDU
    表示没有提供pdu,值为3 (0x00000003)
    public static final int RESULT_ERROR_RADIO_OFF
    表示无线广播被明确地关闭,值为2 (0x00000002)
    public static final int STATUS_ON_ICC_FREE
    表示自由空间,值为0 (0x00000000)
    public static final int STATUS_ON_ICC_READ
    表示接收且已读,值为1 (0x00000001)
    public static final int STATUS_ON_ICC_SENT
    表示存储且已发送,值为5 (0x00000005)
    public static final int STATUS_ON_ICC_UNREAD
    表示接收但未读,值为3 (0x00000003)
    public static final int STATUS_ON_ICC_UNSENT
    表示存储但为发送,值为7 (0x00000007)

3、简单的SMS发送程序

1)、首先,编辑布局文件res/layout/main.xml,达到我们想要的结果,界面如下:

image

图1、程序运行界面

对应的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/txtPhoneNo"/>

    <!-- text's value define in res/values/strings.xml -->
    
    <EditText android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:id="@+id/edtPhoneNo"/>
    
    <TextView android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="@string/txtContent"/>
    
    <EditText android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:minLines="3"
            android:id="@+id/edtContent"/>
   
    <Button android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/btnText"
            android:id="@+id/btnSend"/>
</LinearLayout>

相应的要在res/values/strings.xm中添加上面定义的视图的text的值,如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="txtPhoneNo">Please input phone NO:</string>
    <string name="txtContent">Please input SMS\'s content:</string>
    <string name="btnText">send!</string>
    <string name="app_name">SMS</string>
</resources>

2)、做完这些准备工作之后,我么要开始编写代码实现简单的短信发送了。

通过第一步我们构建好界面之后,现在要在上面的基础上编写业务逻辑了。大致过程为:在java源文件中,获取用户在edtPhoneNo中输入的电话号码,edtContent中输入要发送的内容;然后点击btnSend按钮发送短信,要达到这个目的我们要设置btnSend的OnClickListener以达到当点击它触发发送短信的功能,而且要发送短信就要用到我们前面介绍的SmsManager类提供的方法接口。

设置btnSend的OnClickListener的代码如下:

btnSend.setOnClickListener(new View.OnClickListener() {
    public void onClick(View v) {
        String phoneNo = edtPhoneNo.getText().toString();
        String message = edtContent.getText().toString();
        if (phoneNo.length() > 0 && message.length() > 0){
            //call sendSMS to send message to phoneNo
            sendSMS(phoneNo, message);
        }
        else
            Toast.makeText(getBaseContext(),
                "Please enter both phone number and message.",
                Toast.LENGTH_SHORT).show();
    }
});

发送短信的功能的代码如下:

private void sendSMS(String phoneNumber, String message) {
    // ---sends an SMS message to another device---
    SmsManager sms = SmsManager.getDefault();
    PendingIntent pi = PendingIntent.getActivity(this, 0,

               new Intent(this,TextMessage.class), 0);
    //if message's length more than 70 ,
    //then call divideMessage to dive message into several part

        //and call sendTextMessage()
    //else direct call sendTextMessage()
    if (message.length() > 70) {
        ArrayList<String> msgs = sms.divideMessage(message);
        for (String msg : msgs) {
            sms.sendTextMessage(phoneNumber, null, msg, pi, null);
        }
    } else {
        sms.sendTextMessage(phoneNumber, null, message, pi, null);
    }
    Toast.makeText(TextMessage.this, "短信发送完成", Toast.LENGTH_LONG).show();
}


如果你已经看了第2节介绍的SmsManager类的介绍,代码应该很好理解。在这里要说明的是,sendTextMessage方法中的第4个和第5个参数PendingIntent设为null,这样的话不能根据短信发出之后的状态做相应的事情,如短信发送失败后的提醒、接收者成功接收后的回执……完整的流程源码如下:

package skynet.com.cnblogs.www;

import java.util.ArrayList;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.view.View;
import android.widget.*;

public class TextMessage extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);
        btnSend = (Button) findViewById(R.id.btnSend);
        edtPhoneNo = (EditText) findViewById(R.id.edtPhoneNo);
        edtContent = (EditText) findViewById(R.id.edtContent);

        btnSend.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                String phoneNo = edtPhoneNo.getText().toString();
                String message = edtContent.getText().toString();
                if (phoneNo.length() > 0 && message.length() > 0) {
                    // call sendSMS to send message to phoneNo
                    sendSMS(phoneNo, message);
                } else
                    Toast.makeText(getBaseContext(),
                            "Please enter both phone number and message.",
                            Toast.LENGTH_SHORT).show();
            }
        });
    }

    private Button btnSend;
    private EditText edtPhoneNo;
    private EditText edtContent;

    private void sendSMS(String phoneNumber, String message) {
        // ---sends an SMS message to another device---
        SmsManager sms = SmsManager.getDefault();
        PendingIntent pi = PendingIntent.getActivity(this, 0, new Intent(this,
                TextMessage.class), 0);
        // if message's length more than 70 ,
        // then call divideMessage to dive message into several part ,and call
        // sendTextMessage()
        // else direct call sendTextMessage()
        if (message.length() > 70) {
            ArrayList<String> msgs = sms.divideMessage(message);
            for (String msg : msgs) {
                sms.sendTextMessage(phoneNumber, null, msg, pi, null);
            }
        } else {
            sms.sendTextMessage(phoneNumber, null, message, pi, null);
        }
        Toast.makeText(TextMessage.this, "短信发送完成", Toast.LENGTH_LONG).show();
    }
}

3)运行前,还要在清单文件AndroidManifest.xml中加入允许发送短信的权限:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="skynet.com.cnblogs.www"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".TextMessage"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>
    <uses-permission android:name="android.permission.SEND_SMS"/>
</manifest>

3.1、运行SMS程序给另一个android模拟器发短信

运行上面我们编写的TextMessage程序,另外在Windows的命令行下切换到tools目录下,并输入emulator ?data smsReceiver,我的如下:

image

这样就会启动一个android模拟器,如下所示:(注意它的编号:5556,就是用这个编号与它通信的)

image

图2、通过emulator启动一个android模拟器

通过我们TextMessage程序启动的android模拟器,编写短信:

image

图3、TextMessage程序个5556模拟器发短信

点击发送之后,通过命令行启动的5556号android模拟器会收到我们刚才发送的短信,如下所示:

image

图4、收到短信的提示


tips:

如果通过命令行的emulator启动android模拟器提示“NO DNS servers found!”,这时我们发的短信模拟器是收不到的。

    在Windows下,如果电脑没有介入网络,即找不DNS服务器的话会出现这种情况!
    在Mac下,如果提示这个警告的话,可以这样解决:检查你是否有/etc/resolv.conf文件,如果没有的话,通过下面的命令行

    ln -s /private/var/run/resolv.conf /etc/resolv.conf可以解决。

4、SMS增强(一)

上面我们实现了一个简单的SMS程序,下面我们要对它进行增强!你肯定已经注意到了,我们上面的SMS程序的sendTextMessage方法中的第4个和第5个参数PendingIntent设为null,即sentIntent和deliveryIntent。

第4个参数-sendIntent,当消息成功发送或发送失败都将被触发。广播接收者的结果码,Activity.RESULT_OK表示成功,或RESULT_ERROR_GENERIC_FAILURE、RESULT_ERROR_RADIO_OFF、RESULT_ERROR_NULL_PDU之一表示错误。对应RESULT_ERROR_GENERIC_FAILURE,sentIntent可能包括额外的“错误代码”包含一个无线电广播技术特定的值,通常只在修复故障时有用。第5个参数-deliveryIntent,仅当目标接收到你的SMS消息才触发。

为了跟踪发出的短信的状态,实现和注册Broadcast Receiver(广播接收者)监听传递给sendTextMessage方法的参数Pending Intents。下面我们就实现和注册这个广播接收者:

String SENT_SMS_ACTION="SENT_SMS_ACTION";
String DELIVERED_SMS_ACTION="DELIVERED_SMS_ACTION";

//create the sentIntent parameter
Intent sentIntent=new Intent(SENT_SMS_ACTION);
PendingIntent sentPI=PendingIntent.getBroadcast(
        this,
        0,
        sentIntent,
        0);

//create the deilverIntent parameter
Intent deliverIntent=new Intent(DELIVERED_SMS_ACTION);
PendingIntent deliverPI=PendingIntent.getBroadcast(
        this,
        0,
        deliverIntent,
        0);

//register the Broadcast Receivers
registerReceiver(new BroadcastReceiver(){
    @Override
    public void onReceive(Context _context,Intent _intent)
    {
        switch(getResultCode()){
            case Activity.RESULT_OK:
                Toast.makeText(getBaseContext(),
                        "SMS sent success actions",
                        Toast.LENGTH_SHORT).show();
                break;
            case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
                Toast.makeText(getBaseContext(),
                        "SMS generic failure actions",
                        Toast.LENGTH_SHORT).show();
                break;
            case SmsManager.RESULT_ERROR_RADIO_OFF:
                Toast.makeText(getBaseContext(),
                        "SMS radio off failure actions",
                        Toast.LENGTH_SHORT).show();
                break;
            case SmsManager.RESULT_ERROR_NULL_PDU:
                Toast.makeText(getBaseContext(),
                        "SMS null PDU failure actions",
                        Toast.LENGTH_SHORT).show();
                break;
        }
    }
},
new IntentFilter(SENT_SMS_ACTION));
registerReceiver(new BroadcastReceiver(){
    @Override
    public void onReceive(Context _context,Intent _intent)
    {
        Toast.makeText(getBaseContext(),
                "SMS delivered actions",
                Toast.LENGTH_SHORT).show();                
    }
},
new IntentFilter(DELIVERED_SMS_ACTION));

 

在基本完成了要做的工作,接下来要做的就是将sendTextMessage的第4个和第5个参数改为sentPI、deliverPI,这样工作基本完成,修改后的sendSMS方法如下:

private void sendSMS(String phoneNumber, String message) {
    // ---sends an SMS message to another device---
    SmsManager sms = SmsManager.getDefault();
    String SENT_SMS_ACTION = "SENT_SMS_ACTION";
    String DELIVERED_SMS_ACTION = "DELIVERED_SMS_ACTION";

    // create the sentIntent parameter
    Intent sentIntent = new Intent(SENT_SMS_ACTION);
    PendingIntent sentPI = PendingIntent.getBroadcast(this, 0, sentIntent,
            0);

    // create the deilverIntent parameter
    Intent deliverIntent = new Intent(DELIVERED_SMS_ACTION);
    PendingIntent deliverPI = PendingIntent.getBroadcast(this, 0,
            deliverIntent, 0);

    // register the Broadcast Receivers
    registerReceiver(new BroadcastReceiver() {
        @Override
        public void onReceive(Context _context, Intent _intent) {
            switch (getResultCode()) {
            case Activity.RESULT_OK:
                Toast.makeText(getBaseContext(),
                        "SMS sent success actions", Toast.LENGTH_SHORT)
                        .show();
                break;
            case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
                Toast.makeText(getBaseContext(),
                        "SMS generic failure actions", Toast.LENGTH_SHORT)
                        .show();
                break;
            case SmsManager.RESULT_ERROR_RADIO_OFF:
                Toast
                        .makeText(getBaseContext(),
                                "SMS radio off failure actions",
                                Toast.LENGTH_SHORT).show();
                break;
            case SmsManager.RESULT_ERROR_NULL_PDU:
                Toast.makeText(getBaseContext(),
                        "SMS null PDU failure actions", Toast.LENGTH_SHORT)
                        .show();
                break;
            }
        }
    }, new IntentFilter(SENT_SMS_ACTION));
    registerReceiver(new BroadcastReceiver() {
        @Override
        public void onReceive(Context _context, Intent _intent) {
            Toast.makeText(getBaseContext(), "SMS delivered actions",
                    Toast.LENGTH_SHORT).show();
        }
    }, new IntentFilter(DELIVERED_SMS_ACTION));

    // if message's length more than 70 ,
    // then call divideMessage to dive message into several part ,and call
    // sendTextMessage()
    // else direct call sendTextMessage()
    if (message.length() > 70) {
        ArrayList<String> msgs = sms.divideMessage(message);
        for (String msg : msgs) {
            sms.sendTextMessage(phoneNumber, null, msg, sentPI, deliverPI);
        }
    } else {
        sms.sendTextMessage(phoneNumber, null, message, sentPI, deliverPI);
    }
}

运行之后的,发送短信成功的话就可以看到如下界面:

sms

图5、增强SMS(一)

5、SMS增强(二)

下面这个增强是使SMS能够发送二进制数据。要发送数据要使用SmsManager类的sendDataMessage方法,跟sendTextMessage方法类似,只不过该方法多了一个目标端口的参数,构建该SMS的过程跟前面的类似这里就不在累述。

6、温故知新之Intent

此系列前面简单地接受过意图(Intent),这里再次简单介绍一下,在短信接收程序和使用Intent发送SMS中我们要用到。android应用程序的三大组件——Activities、Services、Broadcast Receiver,通过消息触发,这个消息就称作意图(Intent)。下面以Acitvity为例,介绍一下Intent。Android用Intent这个特殊的类实现在Activity与Activity之间的切换。Intent类用于描述应用的功能。在Intent的描述结构中,有两个最重要的部分:动作和动作对应的数据。典型的动作类型有MAIN、VIEW、PICK、EDIT等,我们在短信接收程序中就用到从广播意图中提取动作类型并判断是否是"android.provider.Telephony.SMS_RECEIVED",进而作深一步的处理。而动作对应的数据则以URI的形式表示。例如,要查看一个人的联系方式,需要创建一个动作为VIEW的Intent,以及表示这个人的URI。

通过解析各种Intent,从一个屏幕导航到另一个屏幕是很简单的。当向前导航时,Activity将会调用startActivity("指定一个Intent")方法。然后,系统会在所有已安装的应用程序中定义的IntentFilter中查找,找到最匹配的Intent对应的Activity。新的Activity接收到指定的Intent的通知后,开始运行。当startActivity()方法被调用时,将触发解析指定Intent的动作,该机制提供了两个关键的好处:

    Activity能够重复利用从其他组件中以Intent形式产生的请求。
    Activity可以在任何时候被具有相同IntentFilter的新的Activity取代。

7、准备工作:SmsMessage类

顾名思义,SmsMessage类是一个表示短信的类,为了更好地了解Android的短信机制及以后更好地编写短信相关程序,这里介绍一下该类的公有方法和常量,及嵌套枚举、类成员。

公有方法:

    public static int[]  calculateLength  (CharSequence  msgBody, boolean use7bitOnly)
    参数:
    msgBody-要封装的消息、use7bitOnly-如果为TRUE,不是广播特定7-比特编码的部分字符被认为是单个空字符;如果为FALSE,且msgBody包含非7-比特可编码字符,长度计算使用16-比特编码。
    返回值:
    返回一个4个元素的int数组,int[0]表示要求使用的SMS数量、int[1]表示编码单元已使用的数量、int[2]表示剩余到下个消息的编码单元数量、int[3]表示编码单元大小的指示器。
    public static int[]  calculateLength  (String  messageBody, boolean use7bitOnly)
    参数和返回值跟上面类似
    public static SmsMessage   createFromPdu  (byte[] pdu)
    从原始的PDU(protocol description units)创建一个SmsMessage。这个方法很重要,在我们编写短信接收程序要用到,它从我们接收到的广播意图中获取的字节创建SmsMessage。
    public String  getDisplayMessageBody()
    返回短信消息的主体,或者Email消息主体(如果这个消息来自一个Email网关)。如果消息主体不可用,返回null。这个方法也很重要,在我们编写短信接收程序也要用到。
    public String   getDisplayOriginatingAddress  ()
    返回信息来源地址,或Email地址(如果消息来自Email网关)。如果消息主体不可用,返回null。这个方法在来电显示,短信接收程序中经常用到。
    public String   getEmailBody  ()
    如果isEmail为TRUE,即是邮件,返回通过网关发送Email的地址,否则返回null。
    public int  getIndexOnIcc  ()
    返回消息记录在ICC上的索引(从1开始的)
    public String   getMessageBody  ()
    以一个String返回消息的主体,如果它存在且是基于文本的。
    public SmsMessage.MessageClass   getMessageClass  ()
    返回消息的类。
    public String   getOriginatingAddress  ()
    以String返回SMS信息的来电地址,或不可用时为null。
    public byte[]  getPdu  ()
    返回消息的原始PDU数据。
    public int  getProtocolIdentifier  ()
    获取协议标识符。
    public String   getPseudoSubject  ()
    public String   getServiceCenterAddress  ()
    返回转播消息SMS服务中心的地址,如果没有的话为null。
    public int  getStatus  ()
    GSM:为一个SMS-STATUS-REPORT消息,它返回状态报告的status字段。这个字段表示之前提交的SMS消息的状态。
    CDMA:为不影响来自GSM的状态码,值移动到31-16比特。这个值由一个error类(25-16比特)和一个状态码(23-16比特)组成。
    如果是0,表示之前发送的消息已经被收到。
    public int  getStatusOnIcc  ()
    返回消息在ICC上的状态(已读、未读、已发送、未发送)。有下面的几个值:SmsManager.STATUS_ON_ICC_FREE、SmsManager.STATUS_ON_ICC_READ、SmsManager.STATUS_ON_ICC_UNREAD、SmsManager.STATUS_ON_ICC_SEND、SmsManager.STATUS_ON_ICC_UNSENT这几个值在上篇的SmsManager类介绍有讲到。
    public static SmsMessage.SubmitPdu   getSubmitPdu  (
           String  scAddress, String  destinationAddress,
           short destinationPort, byte[] data,
           boolean statusReportRequested)
    参数:scAddress - 服务中心的地址(Sercvice Centre address,为null即使用默认的)、destinationAddress - 消息的目的地址、destinationPort- 发送消息到目的的端口号、data - 消息数据。
    返回值:一个包含编码了的SC地址(如果指定了的话)和消息内容的SubmitPdu,否则返回null,如果编码错误。
    public static SmsMessage.SubmitPdu   getSubmitPdu  (
           String  scAddress, String  destinationAddress,
           String  message, boolean statusReportRequested)
    和上面类似。
    public static int  getTPLayerLengthForPDU  (String  pdu)
    返回指定SMS-SUBMIT PDU的TP-Layer-Length,长度单位是字节而不是十六进字符。
    public long  getTimestampMillis  ()
    以currentTimeMillis()格式返回服务中心时间戳。
    public byte[]  getUserData  ()
    返回用户数据减去用户数据头部(如果有的话)
    public boolean  isCphsMwiMessage  ()
    判断是否是CPHS MWI消息
    public boolean  isEmail  ()
    判断是否是Email,如果消息来自一个Email网关且Email发送者(sender)、主题(subject)、解析主体(parsed body)可用,则返回TRUE。
    public boolean  isMWIClearMessage  ()
    判断消息是否是一个CPHS 语音邮件或消息等待MWI清除(clear)消息。
    public boolean  isMWISetMessage  ()
    判断消息是否是一个CPHS 语音邮件或消息等待MWI设置(set)消息。
    public boolean  isMwiDontStore  ()
    如果消息是一个“Message Waiting Indication Group:Discard Message”通知且不应该保存,则返回TRUE,否则返回FALSE。
    public boolean  isReplace  ()
    判断是否是一个“replace short message”SMS
    public boolean  isReplyPathPresent  ()
    判断消息的TP-Reply-Path位是否在消息中设置了。
    public boolean  isStatusReportMessage  ()
    判断是否是一个SMS-STATUS-REPORT消息。

常量值:

    public static final int  ENCODING_16BIT :值为3(0x00000003)
    public static final int  ENCODING_8BIT :值为2 (0x00000002)
    public static final int  ENCODING_UNKNOWN :值为0 (0x00000000) ,用户数据编码单元的大小。
    public static final int  MAX_USER_DATA_BYTES :值为140 (0x0000008c),表示每个消息的最大负载字节数。
    public static final int  MAX_USER_DATA_BYTES_WITH_HEADER :134 (0x00000086),如果一个用户数据有头部,该值表示它的最大负载字节数,该值假定头部仅包含CONCATENATED_8_BIT_REFENENCE元素。
    public static final int  MAX_USER_DATA_SEPTETS :值为160 (0x000000a0) ,表示每个消息的最大负载septets数。
    public static final int  MAX_USER_DATA_SEPTETS_WITH_HEADER :值为153 (0x00000099),如果存在用户数据头部,则该值表示最大负载septets数该值假定头部仅包含CONCATENATED_8_BIT_REFENENCE元素。

嵌套枚举成员SmsMessage.MessageClass的枚举值:

    public static final SmsMessage.MessageClass   CLASS_0
    public static final SmsMessage.MessageClass   CLASS_1
    public static final SmsMessage.MessageClass   CLASS_2
    public static final SmsMessage.MessageClass   CLASS_3
    public static final SmsMessage.MessageClass   CLASS_UNKNOWN

嵌套枚举成员SmsMessage.MessageClass的公有方法:

    public static SmsMessage.MessageClass valueOf (String name):返回值的字符串的值
    public static final MessageClass[]   values  ():返回MessageClass的值数组

嵌套类成员SmsMessage.SubmitPdu的字段:

    public byte[]  encodedMessage :编码了的消息
    public byte[]  encodedScAddress :编码的服务中心地址

嵌套类成员SmsMessage.SubmitPdu的公有方法:

    public String   toString  ()
    返回一个包含简单的、可读的这个对象的描述字符串。鼓励子类去重写这个方法,并提供实现对象的类型和数据。默认实现简单地连接类名、@、十六进制表示的对象哈希码,即下面的形式: getClass().getName() + '@' + Integer.toHexString(hashCode())

8、SMS接收程序

当一个SMS消息被接收时,一个新的广播意图由android.provider.Telepony.SMS_RECEIVED动作触发。注意:这个一个字符串字面量(string  literal),但是SDK当前并没有包括这个字符串的引用,因此当要在应用程序中使用它时必须自己显示的指定它。现在我们就开始构建一个SMS接收程序:

1)、跟SMS发送程序类似,要在清单文件AndroidManifest.xml中指定权限允许接收SMS:<uses-permission android:name="android.permission.RECEIVER_SMS"/>

为了能够回发短信,还应该加上发送的权限。

2)、应用程序监听SMS意图广播,SMS广播意图包含了到来的SMS细节。我们要从其中提取出SmsMessage对象,这样就要用到pdu键提取一个SMS PDUs数组(protocol description units—封装了一个SMS消息和它的元数据),每个元素表示一个SMS消息。为了将每个PDU byte数组转化为一个SMS消息对象,需要调用SmsMessage.createFromPdu。

每个SmsMessage包含SMS消息的详细信息,包括起始地址(电话号码)、时间戳、消息体。下面编写一个接收短信的类SmsReceiver代码如下:

package skynet.com.conblogs.www;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
import android.widget.Toast;

public class SmsReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context _context, Intent _intent) {
        if (_intent.getAction().equals(SMS_RECEIVER)) {
            SmsManager sms = SmsManager.getDefault();

            Bundle bundle = _intent.getExtras();
            if (bundle != null) {
                Object[] pdus = (Object[]) bundle.get("pdus");
                SmsMessage[] messages = new SmsMessage[pdus.length];
                for (int i = 0; i < pdus.length; i++)
                    messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
                for (SmsMessage message : messages) {
                    String msg = message.getMessageBody();
                    String to = message.getOriginatingAddress();
                    if (msg.toLowerCase().startsWith(queryString)) {
                        String out = msg.substring(queryString.length());
                        sms.sendTextMessage(to, null, out, null, null);

                        Toast.makeText(_context, "success",
                                Toast.LENGTH_LONG).show();
                    }
                }
            }
        }
    }
    
    private static final String queryString="@echo";
    private static final String SMS_RECEIVER=
        "android.provider.Telephony.SMS_RECEIVED";
}

上面代码的功能是从接收到的广播意图中提取来电号码、短信内容,然后将短信加上@echo头部回发给来电号码,并在屏幕上显示一个Toast消息提示成功。

9、另一种发送短信的方式:使用Intent

上篇我们使用SmsManager类实现了发送SMS的功能,且并没有用到内置的客户端。实际上,我们很少这样做,自己在应用程序中去完全实现一个完整的SMS客户端。相反我们会去利用它,将需要发送的内容和目的手机号传递给内置的SMS客户端,然后发送。

下面我就向大家介绍如何利用Intent实现利用将我们的东西传递给内置SMS客户端发送我们SMS。为了实现这个功能,就要用到startActivity("指定一个Intent")方法,且指定Intent的动作为Intent.ACTION_SENDTO,用sms:指定目标手机号,用sms_body指定信息内容。java源文件如下所示:

package skynet.com.cnblogs.www;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;


public class TextMessage extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);
        btnSend = (Button) findViewById(R.id.btnSend);
        edtPhoneNo = (EditText) findViewById(R.id.edtPhoneNo);
        edtContent = (EditText) findViewById(R.id.edtContent);

        btnSend.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                String phoneNo = edtPhoneNo.getText().toString();
                String message = edtContent.getText().toString();
                if (phoneNo.length() > 0 && message.length() > 0) {
                     Intent smsIntent=new Intent(Intent.ACTION_SENDTO,
                             Uri.parse("sms:"+edtPhoneNo.getText().toString()));
                     smsIntent.putExtra("sms_body", edtContent.getText().toString());
                     TextMessage.this.startActivity(smsIntent);
                } else
                    Toast.makeText(getBaseContext(),
                            "Please enter both phone number and message.",
                            Toast.LENGTH_SHORT).show();
            }
        });
    }

    private Button btnSend;
    private EditText edtPhoneNo;
    private EditText edtContent;
}

注意代码中的红色粗体部分,就是实现这个功能的核心代码!布局文件maim.xml和值文件string.xml跟上篇中的一样,这里不再累述。运行结果如下图:

http://images.cnblogs.com/cnblogs_com/skynet/WindowsLiveWriter/768129bbcf7f_E171/image_thumb.png

图2、程序主界面

点击send按钮之后,转到内置的SMS客户端并且将我们输入的值传入了,如下图:

image

图3、内容传至内置SMS客户端

发送之后,5556号android模拟器会收到我们发送的消息,如下图:
image

图5、发送之后5556号android模拟器收到消息


10、增强SMS为MMS

我们讲了这么多,都还只是实现了简单的发生SMS的功能,如果我们想发送图片、音频怎么办(⊙o⊙)?不急,现在我们就将第9节介绍的SMS发送程序改造为MMS。

我们可以附加一个文件到我们的消息做为附件发送,用Intent.EXTRA_STREAM和附件资源的Uri做为参数调用putExtra()方法,附加到信息。并设置Intent的类型为mime-type。要注意的是:内置的MMS并不包括一个ACTION_SENDTO动作的Intent接收器,我们需要使用的动作类型是ACTION_SEND,并且目标手机号不在是使用sms:而是address。主要代码如下:

// Get the URI of a piece of media to attach.
Uri attached_Uri = Uri.parse("content://media/external/images/media/1");
// Create a new MMS intent
Intent mmsIntent = new Intent(Intent.ACTION_SEND, attached_Uri);
mmsIntent.putExtra("sms_body", edtContent.getText().toString());
mmsIntent.putExtra("address", edtPhoneNo.getText().toString());
mmsIntent.putExtra(Intent.EXTRA_STREAM, attached_Uri);
mmsIntent.setType("image/png");
startActivity(mmsIntent);

 

将这段代码替换第9节中的红色粗体代码,就完成而来一个MMS的构建。

很多朋友第一次安装安卓模拟器发现无法上网,本教程就来告诉你如何彻底解决这个问题,因为这个问题比较普遍,所以小编就整理成教程发布出来。

一:将网络连接代理设置写入配置数据库

  1、通过命令行或者通过双击emulatoer可执行文件,打开模拟器

  2、在命令行执行adb shell 打开android的控制台(确保环境变量设置正确,即已经把Android_SDK/tools 添加到了PATH(Linux)/path(Windows))

  3、执行ls -l /data/data/com.android.providers.settings/databases/settings.db ,查看系统设置数据库文件是否存在

  4、如果数据库文件存在,执行sqlite3 /data/data/com.android.providers.settings/databases/settings.db,以settings.db为当前scheme启动SQLITE3

  5、执行INSERT INTO system VALUES(99,’http_proxy’, ‘192.168.0.245:8080′); 语句插入数据,其中192.168.0.245是我用的代理服务器IP,8080是端口,请根据具体情况替换

  6、执行SELECT * FROM system; 来查看刚才插入的数据

  7、重启模拟器,以使代理服务器设置生效

  8、可以使用DELETE FROM system WHERE _id=99; 语句来删除代理设置,或者使用UPDATE system SET value = ‘192.168.0.245:8070′WHERE _id=99; 来修改代理服务器设置

二:可能是DNS的问题

  1、用系统的命令进入Android开发包的tools目录

  cd E:android-sdk-windows tools

  2、使用adb的shell,确认系统的各项属性

  adb shell

  getprop

  getprop会列出系统当前的各项属性

  3、得到模拟器的DNS地址

  在结果里可以看到:

  [net.dns1]: [10.0.2.3]

  [net.dns2]: [10.0.2.4]

  4、把dns改成我们自己的DNS

  setprop net.dns1 192.168.1.1

  注:一般TP-LINK及D-LINK的DNS都是192.168.1.1,如果不是请使用ipcnofig /all命令确认。


三:直接带参数启动模拟器

  emulator @default -http-proxy 10.16.xx.xx:8080

  其中default是模拟器的名称

四:在模拟器中设置

  启动模拟器,然后进入Settings->Wireless & networks->Mobile networks->Access Point Names

  然后打开出现在列表中的access point;

  然后下面这样设置:

  - Proxy : your proxy address

  - Port : your proxy port

  - Username : your username if needed, or

  - Password : your password if needed, or


Android模拟器默认的地址是10.0.2.3,默认的DNS也是10.0.2.3,对于在家里上网学习Android的人来讲,一般电脑的IP都是192.168.1.100之类的,不在同一个网段。所以就会出现电脑可以上网但是模拟器不能上网的情况。其实设置方法很简单,只要把模拟器的默认DNS设置成电脑的DNS地址即可。


第一步:用系统的命令进入Android开发包的tools目录

cd X:\...\android-sdk-windows\tool

第二布:使用adb的shell,确认系统的各项属性

adb shell

getprop  

getprop会列出系统当前的各项属性


第三步:得到模拟器的DNS地址


在结果里可以看到:


[net.dns1]: [10.0.2.3]

[net.dns2]: [10.0.2.4]

[net.dns3]: [10.0.2.5]

[net.dns4]: [10.0.2.6]


第四步:把dns改成我们自己的DNS


setprop net.dns1 192.168.1.1


注:一般TP-LINK及D-LINK的DNS都是192.168.1.1,如果不是请使用ipcnofig /all命令确认。


教你轻松解决Android模拟器无法上网问题

1、运行android模拟器,双击桌面的设置图标如下图:


安卓模拟器桌面

安卓模拟器桌面

2、 依次进入:“settings”->“Wireless controls”->“Mobile networks”->“Access Point Names”然后打开出现在列表中的access point,如果已经设置为中文那就是:设置/无线和网络/移动网络/接入点名称,并输入相关设置:具体说明如下:

依次进入:“settings”->“Wireless controls”->“Mobile networks”->“Access Point Names”然后打开出现在列表中的access point,如果已经设置为中文那就是:设置/无线和网络/移动网络/接入点名称。

Proxy(代理):比如:113.12.71.76,如果你不怎么如何设置,可以百度一下去网上找可以使用的代理ip,最好是找国内的,快一些(百度搜索"代理ip")。

Port(端口) :你找的代理ip的端口

Username(用户名):未设置(不要输入,把原来的.也删除)

Password(密码):未设置(不要输入,把原来的.也删除)

Server(服务器):未设置(不要输入,把原来的.也删除)。


如果我们的项目需要做来电及短信的功能,那么我们就得在Android模拟器开发这些功能,本来就来告诉我们如何在Android模拟器上模拟来电及来短信的功能。

在Android模拟器上模拟来电


项目需求要做一个控制来电显示的Android 应用,那么我们就需要在Emulator上模拟来电效果了,下面来看看如何实现Android模拟器上模拟来电

方法如下:
1.单个电话
打开命令行cmd,输入telnet 回车.
然后输入 o localhost 5554 回车,连到Emulator上.
输入gsm call 123456 上面显示OK
这时再去看模拟器,上面就有来电了.
其他:
挂断电话:gsm cancel <模拟打进的电话号码>
设置其他模式:gsm voice unregistered为网络无法联通,denied为紧急呼叫模式

help gsm
allows you to change GSM-related settings, or to make a new inbound phone call

available sub-commands:
   gsm list             list current phone calls
   gsm call             create inbound phone call
   gsm busy             close waiting outbound call as busy
   gsm hold             change the state of an oubtound call to 'held'
   gsm accept           change the state of an outbound call to 'active'
   gsm cancel           disconnect an inbound or outbound phone call
   gsm data             modify data connection state
   gsm voice            modify voice connection state
   gsm status           display GSM status
2. 多个模拟器模拟播打电话
启动多个模拟器,在模拟器A中播模拟器B的端口号码,即可。
3.发送短信
sms send <模拟发送短信的电话号码> <短信内容>
例如:sms send 1234567 Hello
 
 
 
Vista 系统中使用 Telnet服务 器问题
 
【问】 Vista下 输入telnet,提示没有找到该文件,如何找回telnet呢。

【答】 很多在Vista下没有找到telnet程序,如在“开始”的“运行”或“搜索”框中输入telnet,提示没有找到该文件,其实Vista默认是不安装的,由于是针对服务器设置的,在Windows Server 2008中是默认安装的。

解决的方法也很简单,直接安装Vista的系统组件中安装即可,操作步骤,“我的电脑”->“控制面板”->“程序和功能”中,在左边的树图中可以看到“打开或关闭 Windows 功能”,在打开的新对话框“Windows 功能”中可以看到 “telnet服务器”和“telnet客户端”,我们选中这两项,telnet就恢复了,如果仅用于连接远程服务器,我们只需安装“telnet客户端”即可。



Android调试时模拟接收短信与来电

Android模拟器模拟接收短信和来电的方法

关于发送短信和拨打电话,在android里面都很简单,一两句代码就可以搞定。

接收短信和来电有两种方法:

1:用android模拟器自带的Emulator Control(什么?不知道这个在哪里-_-!eclipse左下角有一个+号,选择other,找到打开android目录即可看到。或者在上面的搜索框内输入em.....)


Android调试时模拟接收短信与来电

看到了么?输入incoming number,选择voice就是模拟来电;选择SMS就是模拟发送短信。

其实android模拟器还有一个自己的sim卡号码:15555218135。

在手机中可以找到:

Settings——About phone——Status——Phone number

设置——关于手机——状态——手机号码

2:利用命令行

在cmd下面,可以向模拟器发送一些指令,告诉模拟器我是来电话啦还是来短信了。

打开cmd,输入:telnet localhost 5554

注:vista系统默认没有打开telnet,需要我们手动打开。

5554是模拟器的端口号,大家在模拟器的title上面同样可以看到。

然后输入:gsm call 15555218135

看看模拟器,是不是有一个15555218135的来电?


Android调试时模拟接收短信与来电

再输入:sms send ,如:sms send 15555218135 hello

模拟器是不是有一个发送过来的短信的提示?


Android调试时模拟接收短信与来电

这样我们就可以在模拟器中调试我们处理来电和接收短信的程序了。


Android调试时模拟接收短信与来电


[!--infotagslink--]

相关文章

  • php语言实现redis的客户端

    php语言实现redis的客户端与服务端有一些区别了因为前面介绍过服务端了这里我们来介绍客户端吧,希望文章对各位有帮助。 为了更好的了解redis协议,我们用php来实现...2016-11-25
  • jQuery+jRange实现滑动选取数值范围特效

    有时我们在页面上需要选择数值范围,如购物时选取价格区间,购买主机时自主选取CPU,内存大小配置等,使用直观的滑块条直接选取想要的数值大小即可,无需手动输入数值,操作简单又方便。HTML首先载入jQuery库文件以及jRange相关...2015-03-15
  • Android子控件超出父控件的范围显示出来方法

    下面我们来看一篇关于Android子控件超出父控件的范围显示出来方法,希望这篇文章能够帮助到各位朋友,有碰到此问题的朋友可以进来看看哦。 <RelativeLayout xmlns:an...2016-10-02
  • JS实现的简洁纵向滑动菜单(滑动门)效果

    本文实例讲述了JS实现的简洁纵向滑动菜单(滑动门)效果。分享给大家供大家参考,具体如下:这是一款纵向布局的CSS+JavaScript滑动门代码,相当简洁的手法来实现,如果对颜色不满意,你可以试着自己修改CSS代码,这个滑动门将每一...2015-10-21
  • 利用JS实现点击按钮后图片自动切换的简单方法

    下面小编就为大家带来一篇利用JS实现点击按钮后图片自动切换的简单方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2016-10-25
  • Android开发中findViewById()函数用法与简化

    findViewById方法在android开发中是获取页面控件的值了,有没有发现我们一个页面控件多了会反复研究写findViewById呢,下面我们一起来看它的简化方法。 Android中Fin...2016-09-20
  • Android模拟器上模拟来电和短信配置

    如果我们的项目需要做来电及短信的功能,那么我们就得在Android模拟器开发这些功能,本来就来告诉我们如何在Android模拟器上模拟来电及来短信的功能。 在Android模拟...2016-09-20
  • 夜神android模拟器设置代理的方法

    夜神android模拟器如何设置代理呢?对于这个问题其实操作起来是非常的简单,下面小编来为各位详细介绍夜神android模拟器设置代理的方法,希望例子能够帮助到各位。 app...2016-09-20
  • android自定义动态设置Button样式【很常用】

    为了增强android应用的用户体验,我们可以在一些Button按钮上自定义动态的设置一些样式,比如交互时改变字体、颜色、背景图等。 今天来看一个通过重写Button来动态实...2016-09-20
  • jQuery+slidereveal实现的面板滑动侧边展出效果

    我们借助一款jQuery插件:slidereveal.js,可以使用它控制面板左右侧滑出与隐藏等效果,项目地址:https://github.com/nnattawat/slideReveal。如何使用首先在页面中加载jquery库文件和slidereveal.js插件。复制代码 代码如...2015-03-15
  • Android WebView加载html5页面实例教程

    如果我们要在Android应用APP中加载html5页面,我们可以使用WebView,本文我们分享两个WebView加载html5页面实例应用。 实例一:WebView加载html5实现炫酷引导页面大多...2016-09-20
  • PHP+jQuery翻板抽奖功能实现

    翻板抽奖的实现流程:前端页面提供6个方块,用数字1-6依次表示6个不同的方块,当抽奖者点击6个方块中的某一块时,方块翻转到背面,显示抽奖中奖信息。看似简单的一个操作过程,却包含着WEB技术的很多知识面,所以本文的读者应该熟...2015-10-21
  • 深入理解Android中View和ViewGroup

    深入理解Android中View和ViewGroup从组成架构上看,似乎ViewGroup在View之上,View需要继承ViewGroup,但实际上不是这样的。View是基类,ViewGroup是它的子类。本教程我们深...2016-09-20
  • Android自定义WebView网络视频播放控件例子

    下面我们来看一篇关于Android自定义WebView网络视频播放控件开发例子,这个文章写得非常的不错下面给各位共享一下吧。 因为业务需要,以下代码均以Youtube网站在线视...2016-10-02
  • Android用MemoryFile文件类读写进行性能优化

    java开发的Android应用,性能一直是一个大问题,,或许是Java语言本身比较消耗内存。本文我们来谈谈Android 性能优化之MemoryFile文件读写。 Android匿名共享内存对外A...2016-09-20
  • SQLMAP结合Meterpreter实现注入渗透返回shell

    sqlmap 是一个自动SQL 射入工具。它是可胜任执行一个广泛的数据库管理系统后端指印, 检索遥远的DBMS 数据库等,下面我们来看一个学习例子。 自己搭建一个PHP+MYSQ...2016-11-25
  • Android设置TextView竖着显示实例

    TextView默认是横着显示了,今天我们一起来看看Android设置TextView竖着显示如何来实现吧,今天我们就一起来看看操作细节,具体的如下所示。 在开发Android程序的时候,...2016-10-02
  • android.os.BinderProxy cannot be cast to com解决办法

    本文章来给大家介绍关于android.os.BinderProxy cannot be cast to com解决办法,希望此文章对各位有帮助呀。 Android在绑定服务的时候出现java.lang.ClassCastExc...2016-09-20
  • PHP实现今天是星期几的几种写法

    复制代码 代码如下: // 第一种写法 $da = date("w"); if( $da == "1" ){ echo "今天是星期一"; }else if( $da == "2" ){ echo "今天是星期二"; }else if( $da == "3" ){ echo "今天是星期三"; }else if( $da == "4"...2013-10-04
  • BootStrap栅格系统、表单样式与按钮样式源码解析

    这篇文章主要为大家详细解析了BootStrap栅格系统、表单样式与按钮样式源码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2017-01-23