`
dawuafang
  • 浏览: 1104919 次
文章分类
社区版块
存档分类
最新评论

Android开发小技巧(目录查找是否有你遇到的小问题)

 
阅读更多

1,如何通过代码来重启Android手机?

最省事的是通过shell调用底层reboot命令,不过需要root权限。

	/**
	 * 执行一串shell命令
	 * 
	 * @param cmd
	 */
	private void executeShellCmd(String cmd) {

		try {
			// 申请获取root权限,这一步很重要,不然会没有作用
			Process process = Runtime.getRuntime().exec("su");
			// 获取输出流
			OutputStream outputStream = process.getOutputStream();
			DataOutputStream dataOutputStream = new DataOutputStream(
					outputStream);
			dataOutputStream.writeBytes(cmd);
			dataOutputStream.flush();
			dataOutputStream.close();
			outputStream.close();
		} catch (Throwable t) {
			t.printStackTrace();
		}
	}

执行重启:

executeShellCmd("su -c reboot now");


2,Android通过代码唤醒屏幕并解锁

		//屏幕唤醒并解锁
		PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
		PowerManager.WakeLock wake = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP|PowerManager.SCREEN_DIM_WAKE_LOCK, "bright");
		//点亮屏幕
		wake.acquire();
		wake.release();
		
		KeyguardManager km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
		KeyguardManager.KeyguardLock unlock = km.newKeyguardLock("unLock");
		//解锁
		unlock.disableKeyguard();


3,静态代码块和静态方法的区别

静态代码块是自动执行的,而静态方法是被调用的时候才执行的;

静态方法:如果我们在程序编写的时候需要一个不实例化对象就可以调用的方法,我们就可以使用静态方法,具体实现是在方法前面加上static,如下:

public static void method(){}


在使用静态方法的时候需要注意一下几个方面:

在静态方法里只能直接调用同类中其他的静态成员(包括变量和方法),而不能直接访问类中的非静态成员。这是因为,对于非静态的方法和变量,需要先创建类的实例对象后才可使用,而静态方法在使用前不用创建任何对象。(备注:静态变量是属于整个类的变量而不是属于某个对象的)

静态方法不能以任何方式引用this和super关键字,因为静态方法在使用前不用创建任何实例对象,当静态方法调用时,this所引用的对象根本没有产生。

静态程序块:当一个类需要在被载入时就执行一段程序,这样可以使用静态程序块。


4,在android4.0 应用程序在程序管理面被强制关闭无法开机启动【问题还未解决,遗留】

收不到 android.intent.action.BOOT_COMPLETED 消息 ,android.intent.action.USER_PRESENT消息也无法收到。http://bbs.csdn.net/topics/390313112


5,android:layout_gravity="bottom"不起作用问题?

对于 LinearLayout(父View)

当 android:orientation="vertical" 时, 只有水平方向的设置才起作用,垂直方向的设置不起作用。即:left,right,center_horizontal 是生效的。

当 android:orientation="horizontal" 时, 只有垂直方向的设置才起作用,水平方向的设置不起作用。即:top,bottom,center_vertical 是生效的。


6,MediaPlayer error (1, -2147483648)”问题?

http://www.cnblogs.com/frydsh/p/3443064.html



7,VideoView布局居中和MediaController布局问题

MediaController底部问题:

xml创建一个videoview:

<?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="match_parent"
    android:orientation="vertical" >

    <VideoView
        android:id="@+id/video_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

如果videoview的外层容器的高度是match_parent或者fillparent的话。

视频控制器会和视频播放器分离如图:灰色为分离的部分:

所以在布局中设置videoview的时候最好给videoview外面单独套一个的容器。这个外层容器的高度要设定为wrap_content。这样就会把视频播放器和控制器很好的组合在一起,如下所示:

VideoView布局居中问题:

默认情况下,如果视频分辨率小于屏幕分辨率,VideoView在播放视频时都是在左上角的,影响程序美观。
用下面的方法完美解决,视频居中播放:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:orientation="vertical" >

    <VideoView
        android:id="@+id/videoView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>
其实关键点就在于设置父Layout居中,比如RelativeLayout也可以:

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#000000" >

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_centerVertical="true"
            android:orientation="vertical" >

            <VideoView
                android:id="@+id/video_test_video_view"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="center" />
        </LinearLayout>
    </RelativeLayout>
起作用的就是:android:layout_centerHorizontal="true"; android:layout_centerVertical="true"


8,eclipse无法导出android签名包的问题

Export aborted because fatal lint errors were found.These are listed in the Problems view.Either fix these before running Export again,or turn off "Run full error check when exporting app" in the Android > Lint Error checking preference page.

解决办法:

Window-Preference-Android-Lint Error Checking




9,获取手机信号强度

通过系统服务获取TelephonyManager对象

TelephonyManager tel= (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
		tm.listen(new PhoneStateMonitor(), PhoneStateListener.LISTEN_SIGNAL_STRENGTHS|PhoneStateListener.LISTEN_SERVICE_STATE);

		/*
		 * tel.getNetworkOperator()
		 3G中国是460固定的,
		 中国移动的是 46000
		 中国联通的是 46001
		 中国电信的是 46003
		 *获取国别
		 tel.getSimCountryIso()
		 */
            tel.getDeviceId();//获取设备编号
            tel.getSimCountryIso();//获取SIM卡国别
            tel.getSimSerialNumber();//获取SIM卡序列号    
            tel.getSimState();//获取SIM卡状态
            tel.getDeviceSoftwareVersion();//获取软件版本
            tel.getNetworkOperator();//获取网络运营商代号
            tel.getNetworkOperatorName();//获取网络运营商名称
            tel.getPhoneType();//获取手机制式
            tel.getCellLocation().toString();//获取设备当前位置

实例化或是继承PhoneStateListener接口

	class PhoneStateMonitor extends PhoneStateListener {

		@Override
		public void onSignalStrengthsChanged(SignalStrength signalStrength) {
			super.onSignalStrengthsChanged(signalStrength);
			
			/*
		     * signalStrength.isGsm() 是否GSM信号 2G or 3G
		     * signalStrength.getCdmaDbm(); 联通3G 信号强度
		     * signalStrength.getCdmaEcio(); 联通3G 载干比
		     * signalStrength.getEvdoDbm(); 电信3G 信号强度
		     * signalStrength.getEvdoEcio(); 电信3G 载干比
		     * signalStrength.getEvdoSnr(); 电信3G 信噪比
		     * signalStrength.getGsmSignalStrength(); 2G 信号强度
		     * signalStrength.getGsmBitErrorRate(); 2G 误码率     
		     * 载干比 ,它是指空中模拟电波中的信号与噪声的比值
		     */
				
			System.out.println("IsGsm : " + signalStrength.isGsm()
					+ "  CDMA Dbm : " + signalStrength.getCdmaDbm()
					+ "  CDMA Ecio : " + signalStrength.getCdmaEcio()
					+ "  Evdo Dbm : " + signalStrength.getEvdoDbm()
					+ "  Evdo Ecio : " + signalStrength.getEvdoEcio()
					+ "  Gsm : "+ signalStrength.getGsmSignalStrength()
					+ "  Gsm rate : "+ signalStrength.getGsmBitErrorRate());
		}
	}
服务状态改变

		@Override
		public void onServiceStateChanged(ServiceState serviceState) {
			super.onServiceStateChanged(serviceState);
			/*
			 * ServiceState.STATE_EMERGENCY_ONLY 仅限紧急呼叫
			 * ServiceState.STATE_IN_SERVICE 信号正常
			 * ServiceState.STATE_OUT_OF_SERVICE 不在服务区
			 * ServiceState.STATE_POWER_OFF 断电
			 */
			int pos = serviceState.getState();
			Log.v(TAG, "state change===" + pos);

			switch (pos) {
			case ServiceState.STATE_EMERGENCY_ONLY:
				break;
			case ServiceState.STATE_IN_SERVICE:
				break;
			case ServiceState.STATE_OUT_OF_SERVICE:
				break;
			case ServiceState.STATE_POWER_OFF:
				break;
			}

		}


10,WebView开启自由缩放以及PostUrl

		mWebView = (WebView) findViewById(R.id.app_webview);
		//设置支持JavaScript,默认不支持
		mWebView.getSettings().setJavaScriptEnabled(true);
		// 缩放开关 设置此属性,仅支持双击缩放,不支持触摸缩放(在android4.0是这样,其他平台没试过)
		mWebView.getSettings().setSupportZoom(true);
		// 设置是否可缩放
		mWebView.getSettings().setBuiltInZoomControls(true);
		// 无限缩放
		mWebView.getSettings().setUseWideViewPort(true);
		// 设置Web视图缩小内容以适应屏幕宽度
		mWebView.getSettings().setLoadWithOverviewMode(true);

正常加载URL

mWebView.loadUrl("http://www.test.com/login");


点击URL视图上的某个按钮或组件时,提示打开方式(使用系统自带浏览器或其它工具),如何在当前界面打开新的窗口内容?


解决办法:

		mWebView.setWebViewClient(new WebViewClient() {
			@Override
			public boolean shouldOverrideUrlLoading(WebView view, String url) {

				view.loadUrl(url);// 在当前的webview中跳转到新的url
				return true;
			}
		});

WebView 以 POST 方式加载URL:

		JSONObject json = new JSONObject();
		try {
			json.put("username", "mryang");
			json.put("password", "222222");
			json.put("role", "0");
		} catch (JSONException e) {
			e.printStackTrace();
		}
		mWebView.postUrl("http://www.test.com/login/wap",
				EncodingUtils.getBytes(json.toString(), "UTF-8"));

传送门,这里有关WebView的总结更全面,我就不重复造车轮了~ http://blog.csdn.net/caesardadi/article/details/8530477


11,EditText如何定位光标位置?

代码:edittext.setSelection(int);
例:
et.setText(content);//设置EditText控件的内容
et.setSelection(content.length());//将光标移至文字末尾


12,Android中GridView、ListView的getChildAt方法返回null (通过getChildAt方法取得AdapterView中第n个Item)

ListView或GridView的方法:getChildAt(int index)

一开始以为传入一个绝对的position(就是adapter的第几个item)就可以返回该position的View。但是GridView和ListView对View采用回收机制,简单的说明一下就是:如果屏幕最多可以显示n个子View,那么内存中其实只有n个View,当我们在滚动时,第(n+1)个View复用第1个View,依次类推。所以在GridView和ListView中,getChildAt ( int position ) 方法中position指的是当前可见区域的第几个元素。

				//如果你要获得GridView的第n个View,那么position就是index减去第一个可见View的位置
						int firstVisablePosition = ((ListView) view)
								.getFirstVisiblePosition();
						View itemView = ((ListView) view).getChildAt(index
								- firstVisablePosition);

13,简单实现模仿android 4.0 通知栏动画listview 滑动删除item

左右滑动删除Item,类似与iPhone上滑动删除一样的效果,只是比较粗糙,展示一下实现方式,直接贴上代码:

Activity中:

		listView = getListView();
		array = new ArrayList<String>();
		String aa[] = { "item0", "item1", "item2", "item3", "item4", "item5",
				"item6", "item7", "item8", "item9", "item10", "item11",
				"item12", "item13", "item14", "item15", "item16" };
		for (int i = 0; i < aa.length; i++) {
			array.add(aa[i]);
		}
		adapter = new ArrayAdapter<String>(this,
				android.R.layout.simple_list_item_1, array);
		listView.setAdapter(adapter);

		/**
		 * 添加listview滑动接听
		 */
		listView.setOnTouchListener(new OnTouchListener() {
			float x, y, upx, upy;

			public boolean onTouch(View view, MotionEvent event) {
				if (event.getAction() == MotionEvent.ACTION_DOWN) {
					x = event.getX();
					y = event.getY();
				}
				if (event.getAction() == MotionEvent.ACTION_UP) {
					upx = event.getX();
					upy = event.getY();
					int startPosition = ((ListView) view).pointToPosition(
							(int) x, (int) y);
					int endPosition = ((ListView) view).pointToPosition(
							(int) upx, (int) upy);
					if (startPosition == endPosition && Math.abs(x - upx) > 10) {
						int firstVisablePosition = ((ListView) view)
								.getFirstVisiblePosition();
						View itemView = ((ListView) view)
								.getChildAt(startPosition
										- firstVisablePosition);
						removeListItem(itemView, startPosition);
					}
				}
				return false;
			}

		});

removeListItem:

	/**
	 * 删除item,并播放动画
	 * 
	 * @param rowView
	 *            播放动画的view
	 * @param positon
	 *            要删除的item位置
	 */
	protected void removeListItem(View itemView, final int position) {
		final Animation animation = AnimationUtils.loadAnimation(
				getApplicationContext(), R.anim.item_anim);
		animation.setAnimationListener(new AnimationListener() {
			public void onAnimationStart(Animation animation) {
			}

			public void onAnimationRepeat(Animation animation) {
			}

			public void onAnimationEnd(Animation animation) {
				//动画播放完毕时,array数据源删除相应坐标下的数据,adapter删除相应下item的View
				array.remove(array.get(position));
				adapter.notifyDataSetChanged();
				// animation.cancel();
			}
		});

		itemView.startAnimation(animation);
	}
item_anim.xml

<?xml version="1.0" encoding="utf-8"?> 
<translate xmlns:android="http://schemas.android.com/apk/res/android" 
    android:duration="2000" 
    android:fromXDelta="0" 
    android:fromYDelta="0" 
    android:toXDelta="800" 
    android:toYDelta="0" /> 
效果图:



14,消除manifest中权限警告:Permission is only granted to system apps

在AndroidManifest.xml中声明了一些权限,如:
<uses-permission android:name="android.permission.WRITE_APN_SETTINGS" />就会报错:Permission is only granted to system apps
此类权限仅授予系统级应用,可以修改下Link Error Checking项的安全级别:
In Eclipse: Window -> Preferences -> Android -> Lint Error Checking
在ID列表中,找到ID = ProtectedPermission设置Severity低于Error,比如Warning级别就ok了


15,Unabletoexecutedex:MultipledexfilesdefineLandroi


运行时直接崩溃提示这个错误,一般情况下,跟libs里的jar文件有关系,同一文件(包名)导入了2个,有重复的,可以查看工程build path,尤其是Android Dependencies一定有重复引入的.jar包,解决的方法是在libs删除重复的jar即可。


16,根据屏幕尺寸(密度)设置文字大小的方式

有两种,的一种是根据屏幕尺寸,这种方法相当于自己随意定制,只是根据读取的屏幕宽度来判断取值,代码如下:

	/**
	 * 如有需要可以添加上screenHeight
	 * @param screenWidth
	 * @return
	 */
	public static int adjustFontSize(int screenWidth) {
		
		if (screenWidth <= 240) { // 240X320 屏幕

			return 10;

		} else if (screenWidth <= 320) { // 320X480 屏幕

			return 14;

		} else if (screenWidth <= 480) { // 480X800 或 480X854 屏幕

			return 24;

		} else if (screenWidth <= 540) { // 540X960 屏幕

			return 26;

		} else if (screenWidth <= 800) { // 800X1280 屏幕

			return 30;

		} else { // 大于 800X1280

			return 30;

		}
	}
另一种是根据屏幕密度,如果是布局(xml)上的文字,可以直接使用 sp 作为单位,这个单位的 textSize 是密度单位跟长度的 dp(dip) 类似,自己设置合适大小后,换一个布局(屏幕尺寸)也会随之得到改变。

如果要用 Canvas 之类的画出文本,这个时候需要指定文本的大小为 px 单位。

1,在当前的设备上调节字体至合适的大小
比如:640x480 的屏幕,text 的文本大小为 10

2, 获取当期设备的屏幕像素宽度
在 Activity 里面使用
int screenWidth = getResources().getDisplayMetrics().widthPixels;
3,适当的计算一下
640x480 的屏幕用 10 的文本大小,如果在960或是1080宽度的屏幕下呢?
float textSize = dm.widthPixels / 480.0f * 10;

这样就实现了设定一个中间值,然后根据不同屏幕宽度,来计算文字的大小。


17,图标引擎,AchartEngine的柱状图一些属性的设置:

1. 修改背景色或设置背景图片

// 设置是否应用背景颜色
render.setApplyBackgroundColor(true);
// 设置图表整个边框颜色
render.setMarginsColor(Color.WHITE);
render.setBackgroundColor(Color.WHITE);

2. setAxisTitleTextSize(16);// 设置坐标轴标题文本大小
3. setChartTitleTextSize(20); // 设置图表标题文本大小
4. setLabelsTextSize(15); // 设置轴标签文本大小
5. setLegendTextSize(15); // 设置图例文本大小
6. renderer.setChartTitle( "个人收支表");//设置柱图名称
7. renderer.setXTitle( "名单" );//设置X轴名称
8. renderer.setYTitle( "金额" );//设置Y轴名称
9. renderer.setXAxisMin(0.5);//设置X轴的最小值为0.5
10.renderer.setXAxisMax(5.5);//设置X轴的最大值为5
11.renderer.setYAxisMin(0);//设置Y轴的最小值为0
12.renderer.setYAxisMax(500);//设置Y轴最大值为500
13.renderer.setDisplayChartValues(true);//设置是否在柱体上方显示值
14.renderer.setShowGrid(true);//设置是否在图表中显示网格
15.renderer.setXLabels(0);//设置X轴显示的刻度标签的个数
16.如果想要在X轴显示自定义的标签,那么首先要设置renderer.setXLabels(0); 如果不设置为0,那么所设置的Labels会与原X坐标轴labels重叠
其次我们要renderer.addTextLabel()循环添加
for(int i=0;i<13;i++){
renderer.addTextLabel(i+1,years[i]); //循环添加Xlabel其中显示的label放在years数组中
}
17.renderer.setXLabelsAlign(Align.RIGHT);//设置刻度线与X轴之间的相对位置关系
18.renderer.setYLabelsAlign(Align.RIGHT);//设置刻度线与Y轴之间的相对位置关系
19.renderer.setZoomButtonsVisible(true);//设置可以缩放
20.renderer.setPanLimits(newdouble[] { 0, 20, 0, 140 });//设置拉动的范围
21.renderer.setZoomLimits(newdouble[] { 0.5, 20, 1, 150 });//设置缩放的范围
22.renderer.setRange(newdouble[]{0d, 5d, 0d, 100d}); //设置chart的视图范围
23.renderer.setFitLegend(true);// 调整合适的位置
24.renderer.setClickEnabled(true)//设置是否可以滑动及放大缩小;


18,java Switch中的case后面加上大括号({})和不加大括号的区别

出处:http://www.cnblogs.com/tony-yang-flutter/p/3601056.html

下面给出三段代码大家看一下有什么不同以及哪段代码能够编译通过那段代码编译不能通过,为什么?(Why?)

代码片段一:

int value = 10;
        switch (value) {
        case 1:
            int value1 = 5;
            break;
        case 2:
            int value1 = 6;
            break;
        }
代码片段二:

int value = 10;
        // switch
        switch (value) {
        case 1: {
            int value1 = 5;
            break;
        }
        case 2: 
            int value1 = 8;
            break;
        }
代码片段三:

int value = 10;
        // switch
        switch (value) {
        case 1: {
            int value1 = 5;
            break;
        }
        case 2: {
            int value1 = 8;
            break;
        }
        }
    }
结果:片段1 不能通过编译器的编译,片段2片段3可以通过编译器的编译
想要弄明白这个问题,就要先弄明白Java总变量的作用域问题。我们都知道在java(其他语言也是如此例如:C/C++/java/C#等)中同一个作用域中不能有两个相同的变量名称,(因为如果两个变量名相同容易造成混淆,编译器不知道到底该用那个变量)。

片段1中的两个value1的作用域都在switch的{}内,根据 “同一个作用域中不能有两个名称相同的变量名” 的出片段1肯定不能编译通过

片段2中的两个value1的作用域分别为:

case 1:中的value1的作用域为case1的{}内
case 2:中的value1的作用域为switch的{}内

两个变量的作用域不同,当然可以定义相同的变量名称了。

片段3中的两个value的作用域分别为:

case 1 中的value1的作用域为case 1的{}内,
case 2 中的value1的作用域为case 2的{}内,

所以两个作用域互不交叉,因此编译能够通过。

注意:switch()的{}外面有一个value变量名,此时你不能在case 的{}中定义变量名称为value的变量,因为switch()的{}外的value变量的作用域包含了case{}内的作用域,如下所示:

	private void switchTest() {
		int value = 12;
		switch (32) {
		case 2: {
			int value1 = 23;
			break;
		}
		case 3: {
			int value = 32;//这个value是错误的,在method已经定义
			break;
		}
		}
	}
但是,如果在整个类定义一个value,相当于全局变量(常量),会是什么样的呢?

	private int vlaue;
	private void switchTest() {
		//int value = 12;
		switch (32) {
		case 2: {
			int value = 23;//这个value是可以用的,作用域在case2{}内,和全局value作用域不一样
			break;
		}
		case 3: //即便不加括号,同样可以使用,作用域相当于在switchTest方法中
			int value = 32;
			break;
		
		}
	}

总结使用场合:为了防止在case块中定义相同变量名而出现编译不同过的情况,我们通常会加上{}(目前就知道这种情况,如果以后遇到了再补充)。所以通常情况下是不必加上{}的。该怎么做就怎么做。


19,ListView快速开发常用方法以及常见问题

【1】如果给ListView设置了背景图片:android:background="@drawable/bg",当你拖动,或者点击list空白位置的时候发现ListItem都变成黑色的话,原因是由于:默认的ListItem背景是透明的,而ListView的背景是固定不变的,所以在滚动条滚动的过程中如果实时地去将当前每个Item的显示内容跟背景进行混合运算,所以android系统为了优化这个过程用,就使用了一个叫做android:cacheColorHint的属性,在黑色主题下默认的颜色值是#191919,所以就出现了类似黑色的效果。

解决办法:如果只是换背景的颜色的话,可以直接指定android:cacheColorHint为你所要的颜色,如果你是用图片做背景的话,那也只要将android:cacheColorHint指定为透明(#00000000)就可以了。

【2】不想使用listview自带的divider样式,自定义两种方式:

           android:divider="#f1f1f1"
            android:dividerHeight="1dp"
如果divider="@drawable/divider.png",使用图片资源的话,就不用dividerHeight这个了;

或是,android:divider="@null",android:dividerHeight="0dp",也就是说不使用系统的divider,我们在item中自己在底部添加:

listview_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/list_selector_blue"
    android:gravity="center_horizontal"
    android:orientation="vertical" >

    <!-- 最底部,content内容省略 -->
    <ImageView
        android:id="@+id/tool_list_item_divider"
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:layout_marginLeft="8dp"
        android:background="@drawable/divider_line_01"
        android:contentDescription="@null"
        android:visibility="visible" />

</LinearLayout>
这种方式的好处是divider可随意调整左右的距离,但是不好的地方是,listview最后一个item也会显示出来该divider,想要灵活,还得在代码中动态判断,效果如下:


【3】点击Item时,背景的变化,同样有两种方式,

直接使用listview自带的listSelector属性:android:listSelector="@drawable/list_selector_blue"

或是自定义,在item的xml中,最外层的Layout添加background属性,想要图片,透明,各种颜色都可以随意选择:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/list_selector_blue"
    android:gravity="center_horizontal"
    android:orientation="vertical" >
</LinearLayout>
【4】listview的上边和下边有黑色的阴影

解决办法:给listview加上android:fadingEdge=”none”属性;

【5】listview在拖动的时候背景图片消失变成黑色背景。等到拖动完毕我们自己的背景图片才显示出来
解决办法:给listview加上android:scrollingCache=”false”属性;但是如果你没有给listview使用复杂的背景图片,为了性能考虑,scrollingCache还是要设置为true;

【6】不显示scrollBar

android:scrollbars="none"

【7】drawSelectorOnTop属性

android:drawSelectorOnTop="true" 点击某一条记录,颜色会显示在最上面,记录上的文字被遮住,所以点击文字不放,文字就看不到
android:drawSelectorOnTop="false"点击某条记录不放,颜色会在记录的后面,成为背景色,但是记录内容的文字是可见的


20,android中state_checked和state_selected无法共存的问题


如上图,谁在前,谁的能有效,后者便会失效,应该是Checked事件和selected互斥的原因,建议这两者不要同时存在,使用一个即可。


21,android判断手机SIM卡运营商

	public String getSimInfo() {

		TelephonyManager telManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
		String operator = telManager.getSimOperator();
		String networkOperator = "";
		if (operator != null) {
			if (operator.equals("46000") || operator.equals("46002")
					|| operator.equals("46007")) {
				networkOperator = "中国移动";
			} else if (operator.equals("46001")) {
				networkOperator = "中国联通";
			} else if (operator.equals("46003")) {
				networkOperator = "中国电信";
			}
		}
		return networkOperator;
	}

22,多线程获取验证码(图片加载器)

直接上代码了:

package com.vixtel.netvista.sxcmcc.common;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.CoreConnectionPNames;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;

/**
 * @author yangxiaolong
 * @2015-3-10
 */
public class ImageLoader implements Runnable {

	/** 回调函数,传回一个Bitmap对象 */
	public interface onLoadListener {
		void onLoadFinished(Bitmap bitmap);
	};

	private static final String TAG = ImageLoader.class.getSimpleName();

	/** 回调监听 */
	protected onLoadListener onloadListener;

	/** 目标地址 */
	private String requestUrl;

	/** 打印LOG标记 */
	private boolean isDebug = true;

	public void setOnloadListener(onLoadListener onloadListener) {
		this.onloadListener = onloadListener;
	}

	public ImageLoader(String url) {
		requestUrl = url;
	}

	public void startLoad() {
		new Thread(this).start();
	}

	@Override
	public void run() {
		// requestByHttpClient();
		requestByHttpURLConnection();
	}

	/**
	 * 以HttpClient方式下载数据
	 */
	protected void requestByHttpClient() {
		HttpClient client = new DefaultHttpClient();

		client.getParams().setParameter(
				CoreConnectionPNames.CONNECTION_TIMEOUT, 30000);
		client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 30000);

		URI uri;
		InputStream is = null;
		BufferedInputStream bis = null;
		Bitmap bitmap = null;
		try {
			uri = new URI(requestUrl);
			debug("httpGet requestUrl:" + requestUrl + "  sessionId:"
					+ NetClientSession.sessionId);
			HttpGet get = new HttpGet(uri);
			// 如果需要sessionid的话,传入
			get.setHeader("Cookie", "nts-session-id="
					+ NetClientSession.sessionId);
			HttpResponse response = client.execute(get);
			debug("http response statusLine:" + response.getStatusLine());
			debug("http response entity:" + response.getEntity().toString());
			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				is = response.getEntity().getContent();
				bis = new BufferedInputStream(is);
				bitmap = BitmapFactory.decodeStream(bis);
				// 裁剪尺寸
				// Bitmap.createScaledBitmap(bitmap, dstWidth, dstHeight,
				// filter);
			}

			if (onloadListener != null) {
				onloadListener.onLoadFinished(bitmap);
			}

		} catch (URISyntaxException e) {
			e.printStackTrace();
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			client.getConnectionManager().shutdown();
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				is = null;
			}
			if (bis != null) {
				try {
					bis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				bis = null;
			}
		}

	}

	/**
	 * 以HttpURLConnection方式下载数据
	 */
	protected void requestByHttpURLConnection() {

		URL url = null;

		HttpURLConnection conn = null;
		BufferedInputStream bis = null;
		Bitmap bitmap = null;
		try {
			url = new URL(requestUrl);
			debug("HttpURLConnection requestUrl:" + requestUrl + "  sessionId:"
					+ NetClientSession.sessionId);
			conn = (HttpURLConnection) url.openConnection();
			conn.setReadTimeout(30000);
			conn.setConnectTimeout(30000);
			conn.setRequestMethod("GET");
			// HttpURLConnection方式添加cookie等参数【如果需要cookie参数的话】
			conn.addRequestProperty("Cookie", "nts-session-id="
					+ NetClientSession.sessionId);
			if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
				bis = new BufferedInputStream(conn.getInputStream());

				// 方法一
				// bitmap = BitmapFactory.decodeStream(bis);

				// 方法二
				byte[] buffer = new byte[1024];
				int len = 0;
				ByteArrayOutputStream bos = new ByteArrayOutputStream();
				while ((len = bis.read(buffer)) != -1) {
					bos.write(buffer, 0, len);
				}
				byte[] data = bos.toByteArray();
				bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
			}

			if (onloadListener != null) {
				onloadListener.onLoadFinished(bitmap);
			}

		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (conn != null) {
				conn.disconnect();
				conn = null;
			}
			if (bis != null) {
				try {
					bis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				bis = null;
			}
		}

	}

	private void debug(String msg) {
		if (isDebug) {
			Log.d(TAG, msg);
		}
	}

}

在跳转到相应界面时:

	ImageLoader imageloader = new ImageLoader(
				"http://XXXXXXXXX/getVerifyCodeImage?&width=95&height=21");
		imageloader.setOnloadListener(this);
		imageloader.startLoad();

在回调接口里:

	@Override
	public void onLoadFinished(final Bitmap bitmap) {
		if (bitmap != null) {
			mHandler.post(new Runnable() {

				@Override
				public void run() {
					verifyCodeView.setImageDrawable(new BitmapDrawable(bitmap));
				}
			});
		}
	}

效果图:



23,解决真机调试时Eclipse DDMS上打不开/data等目录的问题

比如我们在项目中使用了SQLite存储技术,然后想把保存的db文件,导入到电脑中,在Eclipse的File Explorer寻找data/data/应用名称/db 中便可以做到这个,不过首先是需要满足一个条件:手机ROOT

首先root:现在root简单多了,不像以前必须要通过破解程序强行刷入,现在可以利用诸如ROOT大师,一键获取ROOT便可以搞定了,这种样子类似于假的root,并不是深度,相比起来会安全很多。

其次,下载一个类似于RE管理器这样的软件,可以在手机上查看data、system等目录:


打开后,应该就会弹出root权限申请,同意后,顶部调成:挂载为可读写,这样的话,我们就能读写所有的文件夹了,现在手机打开data,肯定没问题吧,但是我们切换到Eclipse的DDMS下,File Explorer,还是打不开data,为什么?还有一步,如下图:

长按data文件夹,权限设定,其他组也勾选上读和写-同时应用到所有子文件和子文件夹,确定

接下来,再在DDMS下,打开data,试一试:

搞定


24,java中SimpleDateFormat 和android中DateFormat对日期的格式化差异

首先我们看SimpleDateFormat 的实现:

		SimpleDateFormat simpledateformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
		String now = simpledateformat.format(new Date());
HH代表24小时制,hh代表12小时制

然后我们看下android版的DateFormat

				long time = 1427277590213L;
				String now = DateFormat.format("yyyy-MM-dd kk:mm:ss", time).toString();
注意到了吧,小时如果用HH会出问题,在某些手机上识别不了,会直接显示HH,所以只能用hh,这个代表了12小时制,如果我们用此API想实现24小时制的,就得用kk,然后就没问题了。

25,ListView 添加FooterView相关问题汇总

【footerview添加后看不到】,请记得,一定要在listview.setAdapter()之前addFooterView,否则无效的。

【HeaderView和FooterView不可选择或点击】,我们的headerView和footerView添加到listview后其实是相当于一个item,所以系统会自动加上点击和选中的效果,如果想禁用的话,使用这个方法:

public void addFooterView(View v, Object data, boolean isSelectable) 
public void addHeaderView(View v, Object data, boolean isSelectable)
如果在view里已经定义好相关数据,第二个参数就是null,第三个参数设为false,即不可选择

【HeaderView和FooterView动态添加和删除】,直接listview.removeFooterView()感觉太过暴力,如果footerview设置View visible为Gone的话,虽然内容不显示了,但是这块区域还是会被占用(显示),有一个不是办法的办法,如下:

需要隐藏时:

footerView.setVisibility(View.GONE);
footerView.setPadding(0, -footerLayout.getHeight(), 0, 0);
需要显示时:

footerView.setVisibility(View.VISIBLE);
footerView.setPadding(0, 0, 0, 0);

【使用ListView的footerView实现上拉加载更多的效果】

load_more.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="60dp" >

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="60dp"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true" >

        <ProgressBar
            android:id="@+id/loadmore_progressbar"
            style="@style/Progress_circle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginRight="2dp"
            android:visibility="visible" />

        <TextView
            android:id="@+id/loadmore_description"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginLeft="2dp"
            android:layout_toRightOf="@+id/loadmore_progressbar"
            android:text="加载中..."
            android:textColor="#999999"
            android:textSize="14sp" />
    </RelativeLayout>

</RelativeLayout>

java

		loadMoreView = getLayoutInflater().inflate(
				R.layout.listview_footview_loadmore, null, true);
		//before listview.setAdapter
		 mListView.addFooterView(loadMoreView, null, false);
实现OnScrollListener

	@Override
	public void onScrollStateChanged(AbsListView view, int scrollState) {

		if (scrollState == OnScrollListener.SCROLL_STATE_IDLE
				&& lastItemIndex == recordAdapter.getCount()) {
			System.out.println("onScrollStateChanged:" + scrollState
					+ "   count:" + recordAdapter.getCount());
			// 假如总共有50条记录
			if (recordAdapter.getCount() >= 50) {
				mListView.removeFooterView(loadMoreView);
				Toast.makeText(this, "加载完毕", Toast.LENGTH_SHORT).show();
			} else {

				for (int i = 0; i < 5; i++) {
					insertData();
				}
				recordList = recordManager.findAll();
				recordAdapter.notifyDataSetChanged();

			}

		}

	}

	@Override
	public void onScroll(AbsListView view, int firstVisibleItem,
			int visibleItemCount, int totalItemCount) {

		// 第一个可见的item+当前界面所有可视的item总数减去1
		lastItemIndex = firstVisibleItem + visibleItemCount - 1;

	}
效果图



26,正确获取手机屏幕屋里尺寸,密度,密度DPI

在一个低密度的小屏手机上,仅靠上面的代码是不能获取正确的尺寸的。比如说,一部240x320像素的低密度手机,如果运行上述代码,获取到的屏幕尺寸是320x427。因此,研究之后发现,若没有设定多分辨率支持的话,Android系统会将240x320的低密度(120)尺寸转换为中等密度(160)对应的尺寸,这样的话就影响的APP的屏幕适配。所以,需要在工程的AndroidManifest.xml文件中,加入supports-screens节点,具体的内容如下:

    <supports-screens
        android:anyDensity="true"
        android:largeScreens="true"
        android:normalScreens="true"
        android:resizeable="true"
        android:smallScreens="true"
        android:xlargeScreens="true" />
这样的话,当前的Android程序就支持了多种分辨率,那么就可以得到正确的物理尺寸了:

		DisplayMetrics dm = new DisplayMetrics();
		// 取得窗口属性
		getWindowManager().getDefaultDisplay().getMetrics(dm);
		// 窗口的宽度
		int screenWidth = dm.widthPixels;// 屏幕宽度(像素)
		// 窗口高度
		int screenHeight = dm.heightPixels;// 屏幕高度(像素)
		float density = dm.density;// 屏幕密度(0.75 / 1.0 / 1.5)
		int densityDpi = dm.densityDpi;// 屏幕密度DPI(120 / 160 / 240)


27,JNI开发遇到Eclipse报错“Unresolved inclusion jni.h”的解决办法

在配置NDK开发环境的适合,当JDK,Eclipse,Android SDK,一切就绪时,我们创建了一个Demo,并在项目添加了 Native Support支持,发现在编辑xx.cpp的时候,由于include的头文件都无法加载(或识别),导致代码内容symbol都出现错误,解决办法很简单。

我们只在Eclipse-Peference-Android-JDK,添加了JDK的路径,其实光这么做是不够的,还需要添加一个JDK的PATH,配置一下bash_profile 打开Terminal

输入命令 pico .bash_profile
首先添加一行 export PATH=${PATH}:/Users/admster/android/android-ndk-r10e
然后再来一行 A_NDK_ROOT=/Users/admaster/android/android-ndk-r10e
最后来一行 export A_NDK_ROOT


如上图所示,control+x 输入y 保存一下,enter,关闭终端,如果这个时候你还开启着Eclipse,关闭,重新打开,是不是cpp的错误解决了?


如果你发现我的方法还是解决不了,那么附上传送门,领一哥们解决办法就是删除.project里的部分内容,同时删除.cproject文件,重新给项目添加Native Support支持。

http://blog.csdn.net/zhubin215130/article/details/39347873


28,Android JNI NDK开发中的Method 'NewStringUTF' could not be resolved问题

在JNI开发时,我们编辑c或cpp文件,添加一个method时,有时候会提示这样的错误,但是好像明明已经导入了相关类的头文件,解决办法如下:

选中项目右键-properties,左侧tab列表选中C/C++ General-Code Analysis,右侧内容区域选择:Use Project settings,寻找到Method cannot be resolved一行,取消勾选,apply,保存,这样再编辑代码时,便不会提示这样的警告和错误了。


这只是设置在当前项目下,如果其他工程有遇到,同样的方式。http://www.oschina.net/question/95475_89610

29,JNI开发 使用javah,生成.h头文件时出现无法访问android.app,Activity的错误的解决

在jdk6时,是在bin/classes目录下执行命令,生成.h文件;在jdk7及以上时,是在src目录下执行命令,生成.h文件,具体如下图:



30,Android NDK java.lang.UnsatisfiedLinkError: findLibrary returned null

目标的.c或.cpp文件最好不要以lib为开头,这样自动生成的so文件是以libXXX.so为命名规则,在代码中调用:

	public native String getReply();

	static {
		System.loadLibrary("hellojni");
		Log.d("JNIDemo", "so success load~~~");
	}

hellojni时,会自动寻找项目libs/armeabi中的libhellojni.so,如果我们的c/cpp文件是以lib开头的,那么生成的so应该是liblibXXX.so,如果单独是一个lib开头,就会出现这样的错误,为了不引起歧义,自己的cpp文件还是不要加lib了,就用系统自己加的为准。

其实引起这个错误的问题有多个方面,不仅仅是我说的这个,放个传送门大家自己看:http://stackoverflow.com/questions/9037966/android-ndk-java-lang-unsatisfiedlinkerror-findlibrary-returned-null


31,jni/hellocpp/main.cpp:16:18: error: base operand of '->' has non-pointer type 'JNIEnv {aka _JNIEnv}'

这个错误一般发生在我们进行NDK(JNI)开发时的C/C++文件中,一眼望去是识别不了函数或是变量type,其实是C和C++对于这个返回函数:NewStringUTF的不同使用方法~

代码的写法是:

jstring Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
jobject thiz, jstring str, jint i ){
return (*env)->NewStringUTF(env, "Hello from JNI !");
}
错误在于:

(*env)->NewStringUTF(env, "Hello from JNI !");这一行,这是c的写法

而cpp的话,需要改写成:env->NewStringUTF( "Hello from JNI !");


32,NDK开发时Native method not found错误以及如何生成一个公用的SO库

出现Native method not found这个错误有很多因素,最常见的就是C/C++函数声明时大小写(Java)或是路径不对,导致SO调用时找不到相应的类

JNIEXPORT jstring JNICALL Java_com_admaster_jnitest_AppMain_getReply
(JNIEnv *, jobject);

其次,如果使用C++代码,别忘了在cpp声明:

extern "C" {
//..
}

放上传送门一个:http://blog.csdn.net/liranke/article/details/41078137

其实想说的是,我的Project01,添加了Native Support支持,并且进行了NDK开发,build run在libs/armvabi下生成了.so文件(比如方法路径是:com_ndk_test_AppMain_Method1),但是我拷贝到Project02的libs下,同时在需要使用功能的地方加载了so库,使用某一个功能(method)时,出现了native method not found的错误,这是很正常的,在project02下,是完全不同的package,它是找不到com_ndk_test_AppMain_Method1这个路径下的函数的~

所以,想做一个可以共同使用的so库,就需要另一个项目,创建一个以so里方法命名的package和类名,在project02创建一个:com.ndk.test的package,创建一个AppMain的类文件,在此loadLibrary和声明 Native Method。

像baidu地图,都是so库结合SDK一起使用的,在它自己的SDK里,加载SO,然后提供公共接口和功能供用户使用。


33,NDK开发,如何添加LOG调试以及出现unresolvedANDROID_LOG_INFO 和undefined reference to `__android_log_print' 错误

在NDK中添加LOG函数,并且可以在logcat中输出的办法:

第一步 在.h或是.c或是.cpp中头部添加:

#include <android/log.h>

#define LOG_TAG "ctool"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

__android_log_print(ANDROID_LOG_INFO,LOG_TAG,TITLE)
第一个参数ANDROID_LOG_INFO(还有ANDROID_LOG_ERROR等),表示什么类型的输出,上面的函数相当于android的java代码的Log.i(LOG_TAG,TITLE),第二个参数就是logcat里的tag,第三个就是打印的内容,再详细可以log.h中查看。

__android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,“***”) // LOG类型:debug
__android_log_print(ANDROID_LOG_INFO,LOG_TAG,“***”) // LOG类型:info
__android_log_print(ANDROID_LOG_WARN,LOG_TAG,“***”) // LOG类型:warning
__android_log_print(ANDROID_LOG_ERROR,LOG_TAG,“***”) // LOG类型:error
__android_log_print(ANDROID_LOG_FATAL,LOG_TAG,“***”) // LOG类型:Verbose

第二步 在Android.MK文件中添加:

LOCAL_LDLIBS += -llog

如果是用BUILD_SHARED_LIBRARY生成.so,那么在Android.apk中添加下面语句
LOCAL_LDLIBS:=-L$(SYSROOT)/usr/lib -llog(注:若生成static的.a,只需添加 LOCAL_LDLIBS:=-llog )


34,签名打包时proguard returned with error code 1混淆的错误:jpush [cn/jpush/android/a/a.<clinit>()V])

在console上看一下是不是极光推送那边出的问题,如果是的话,很大几率是你的Proguard版本过低,下载4.x以上的proguard.jar然后替换到sdk的proguard目录下即可。


35,'<>' operator is not allowed for source level below 1.7

这个错误基本上出现于导入项目到Eclipse时,原因是当前该项目在Eclipse下的JRE环境与项目要求不一致,解决办法如下:

右键项目-属性-Java-Compiler,在右侧:Compiler Compliance level调整到1.7,即可。


36,TextView在xml里配置onClick事件不起作用的问题

android:clickable="true"

android:onClick="titleAction"

一定要记得加上clickable为true,默认为false,我们又不在代码中setOnclickListener,所以就无法响应事件咯,其它可以在xml添加onClick的组件也是同样道理。



版权声明:本文为博主原创文章,未经博主允许不得转载。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics