读书人

转的稿件

发布时间: 2012-09-04 14:19:30 作者: rapoo

转的文章
1、 在需要网络连接的程序中,首先检查网络连接是否正常,如果没有网络连接,那么就不需要执行相应的程序。

检查网络连接的方法如下:

ConnectivityManager mConnectivity; TelephonyManager mTelephony; …… // 检查网络连接,如果无网络可用,就不需要进行连网操作等 NetworkInfo info = mConnectivity.getActiveNetworkInfo(); if (info == null || !mConnectivity.getBackgroundDataSetting()) { return false; } //判断网络连接类型,只有在3G或wifi里进行一些数据更新。 int netType = info.getType(); int netSubtype = info.getSubtype(); if (netType == ConnectivityManager.TYPE_WIFI) { return info.isConnected(); } else if (netType == ConnectivityManager.TYPE_MOBILE && netSubtype == TelephonyManager.NETWORK_TYPE_UMTS && !mTelephony.isNetworkRoaming()) { return info.isConnected(); } else { return false; }

  目前Android操作系统的手机大部分支持WIFI,GSM,3G网络通信,但是每次链接到网络时只能选择一种链接方式,

  比如运营商定制的,还必须要求特定的网络环境(CMWAP,CTWAP等)如果要切换网络还需要先关闭现有的网络,




<intent filter>
<action android:name="android.net.conn.
CONNECTIVITY_CHANGE"/>

  然后再启动新的网络,这个转换过程还需要一定的时间,

  可能程序这时还需要知道心的网络是否链接成功后自动登录到新的网络服务器中,

  那怎么知道几时链接成功呢?这个时间需要多久呢?

  也许用一个线程去监听网络状态是否链接成功;

  我们可以用另外一种方法,PhoneStateListener

  没错,你没看错,就是用PhoneStateListener。

  很多应用PhoneStateListener都是监听来电去电,PhoneStateListener还可以监听网络断开、

  正在连接和连接成功。

 1 final TelephonyManager mTelephonyMgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); 
 2 mTelephonyMgr.listen(new PhoneStateListener(){
 3           
 4   @Override
 5   public void onDataConnectionStateChanged(int state) {
 6     switch(state){
 7       case TelephonyManager.DATA_DISCONNECTED://网络断开
 8          break;
 9       case TelephonyManager.DATA_CONNECTING://网络正在连接
10          break;
11       case TelephonyManager.DATA_CONNECTED://网络连接上
12          break;
13     }
14   }
15             
16   }

  PhoneStateListener.LISTEN_DATA_CONNECTION_STATE); 

  我们只要重载onDataConnectionStateChanged方法,根据state判断做相应的处理。

public static void connectNetwork(String apnApType)
{
connectivity.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, apnApType);
}

<RelativeLayout xmlns:Android="http://schemas.android.com/apk/res/android"

android:orientation="vertical" android:layout_width="fill_parent"

android:layout_height="fill_parent">

<RelativeLayout android:id="@+id/listHeader"

android:background="@drawable/jbshape" android:layout_alignParentTop="true"

android:gravity="center_horizontal" android:layout_width="fill_parent"

android:layout_height="wrap_content">

<TextView android:text="IdeasAndroid 列表演示" android:textColor="#000000"

android:textSize="18dip" android:layout_width="wrap_content"

android:layout_height="wrap_content"></TextView>

</RelativeLayout>

<RelativeLayout android:id="@+id/listFooter"

android:background="@drawable/jbshape" android:gravity="center_horizontal"

android:layout_alignParentBottom="true" android:layout_width="fill_parent"

android:layout_height="wrap_content">

<Button android:id="@+id/prePage" android:layout_width="wrap_content"

android:layout_height="wrap_content" android:text="上一页"

android:layout_alignParentLeft="true"></Button>

<Button android:layout_width="wrap_content"

android:layout_gravity="right" android:layout_height="wrap_content"

android:text="下一页" android:layout_toRightOf="@id/prePage"></Button>

</RelativeLayout>

<ListView android:id="@+id/myListView" android:layout_width="fill_parent"

android:layout_height="fill_parent" android:layout_below="@id/listHeader"

android:layout_above="@id/listFooter">

</ListView>

</RelativeLayout>


endcall除了挂机还有一个默认的功能就是sleep,长按为power的长按功能。我需要将这个功能修改为home键的press and long press。

按键事件的处理在frameworks/policies/base/phone/com.android.internal.policy.impl/PhoneWindowManager.java中,

需要修改的地方如下:

static final int ENDCALL_HOME = 0x1;
static final int ENDCALL_SLEEPS = 0x2;
static final int DEFAULT_ENDCALL_BEHAVIOR = ENDCALL_HOME; //修改默认的endcall功能为回到主界面

但是,修改之后,发现速度特别慢,找到代码分析:

boolean goHome() {
if (false ) {
// This code always brings home to the front.
try {
ActivityManagerNative.getDefault().stopAppSwitches();
} catch (RemoteException e) {
}
sendCloseSystemWindows();
startDockOrHome();
} else {
// This code brings home to the front or, if it is already
// at the front, puts the device to sleep.
try {
ActivityManagerNative.getDefault().stopAppSwitches();
sendCloseSystemWindows();
Intent dock = createHomeDockIntent();
if (dock != null) {
int result = ActivityManagerNative.getDefault()
.startActivity(null, dock,
dock.resolveTypeIfNeeded(mContext.getContentResolver()),
null, 0, null, null, 0, true /* onlyIfNeeded*/, false);
if (result == IActivityManager.START_RETURN_INTENT_TO_CALLER) {
return false;
}
}
int result = ActivityManagerNative.getDefault()
.startActivity(null, mHomeIntent,
mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
null, 0, null, null, 0, true /* onlyIfNeeded*/, false);
if (result == IActivityManager.START_RETURN_INTENT_TO_CALLER) {
return false;
}
} catch (RemoteException ex) {
// bummer, the activity manager, which is in this process, is dead
}
}
return true;
}

把false改为true就行了,强制回到主界面,我才不需要等待别的处理。

这样endcall的press就成功了。

修改long press,这里要提一下的是,只要keyDown,我们的event.value=1,但是如果按下马上松开,就会触发keyup,event.value=0,而长按不会触发keyup。


代码如下:

在interceptKeyTq(RawInputEvent event, boolean screenIsOn)方法中:

int type = event.type;
int code = event.keycode;
boolean down = event.value != 0;
if (type == RawInputEvent.EV_KEY) {
if (code == KeyEvent.KEYCODE_ENDCALL
|| code == KeyEvent.KEYCODE_POWER) {
if ((code == KeyEvent.KEYCODE_ENDCALL) && !down) { //这里是我浪费时间最多的地方

//本来想和mHandler.removeCallbacks(mPowerLongPress);放在一起,但是触发了press事件

//后来推测可能是callback没有remove掉,然后放到最上方识别key的地方remove,这样就可以了。
mHandler.removeCallbacks(mEndCallLongPress);
}

if(code == KeyEvent.KEYCODE_POWER) {
mHandler.postDelayed(mPowerLongPress,
ViewConfiguration.getGlobalActionKeyTimeout()); //原始代码
} else {
Log.i("jacky.yang", "-----"+ event.value +"-----");
mHandler.postDelayed(mEndCallLongPress,
ViewConfiguration.getGlobalActionKeyTimeout());
}

Runnable mEndCallLongPress = new Runnable() {
public void run() {
/*
* Eat the longpress so it won't dismiss the recent apps dialog when
* the user lets go of the home key
*/
mShouldTurnOffOnKeyUp = false;
mHomePressed = false;
performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_RECENT_APPS);
showRecentAppsDialog();
}
};

在endcall的callback中,必须先disable掉单击的触发事件。


private void setWakeLock(boolean hold) {
if (DEBUG) Log.d(LOG_TAG, (hold ? "hold" : " releas") + "ing wake lock");
Window win = getWindow();
WindowManager.LayoutParams winParams = win.getAttributes();
winParams.flags |= (WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
if (hold)
winParams.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
else
winParams.flags &= (~WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
win.setAttributes(winParams);
}

读书人网 >移动开发

热点推荐