现在的位置: 首页 > 综合 > 正文

第三天:手机归属地

2018年01月29日 ⁄ 综合 ⁄ 共 7625字 ⁄ 字号 评论关闭
安卓DEMO里面的示例,我应该把安卓DEMO里面的示例看过一遍

1. 通过网络获取归属地 缺陷: 网络

2. 本地的数据库  (有一个电话号码的归属地)
sqlite的数据库 


android下的数据库 .db 
一定要有一张 android_metadata 




程序 开发中有一些大的素材 和资源文件 
1. res目录建立一个文件夹 raw  在R文件中生成一个id的引用 
最好推荐存放一些小的资源 几十k 几百K 



2. assets 资产目录
不会把里面的内容在R 文件中生成一个引用
assets 不推荐我们存在1M 文件
appt 打包工具可能出现问题.


3. javame 
把大的资源文件放置在src目录下 通过类加载器的方式 获取这个资源文件
导致我们应用程序的体积非常大.


4. 程序的主apk很小 素材文件 资源文件从服务器上下载 
sdcard rom 
一般游戏软件  大的oa软件 
地图软件 离线地体20~100M~ 1G 

菜谱程序: 


我们知道在子线程不能对UI进行更改,为什么Progress可以不断的更新进度呢?
因为底层它已经实现是通过Handler更新的,你可以看源码,而且可以在子线程里面
写dismiss,其实底层就是显示:
   public void dismiss() {
        if (Thread.currentThread() != mUiThread) {
            mHandler.post(mDismissAction);
        } else {
            mDismissAction.run();
        }
    }
如果不是主线和就告诉Handler去结束它,如果是主线程直接结束。

Message中what和obj区别?

学会从API demo里面找资源,先从上面的一些字符也就是资源文件找--》布局文件--》JAVA文件。
非常好的思路方法,要多学习方法。

有一个非常好的晃动动画,要学习。





没有使用类的成员变量直接做成静态方法。

发个东西:
File-based resource names must contain only lowercase a-z, 0-9, or _.
安卓中的XML文件只能是小写字母数字和下划线。

又是一个教训。子线程中不能改动主界面。
例如子线程里面不能调用一个Toast,因为它改变了主界面。操 ,太坑爹了。
记住了,所有在子线程里操作界面发生错误都是这句话:
Can't create handler inside thread that has not called Looper.prepare()
pd.setTitle("提示");
pd.setIcon(R.drawable.icon5);
pd.setCancelable(false);
pd.setMessage("正在下载数据库");
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.show();//pd的这些操作放在子线程里面就是Can't create handler inside thread that has not called Looper.prepare()
new Thread(){
	public void run() {
		//提示用户下载数据库
		String dbUrl = getResources().getString(R.string.addressdburl);
		try {
			DownloadApkTask.download(dbUrl, Environment.getExternalStorageDirectory()+"/address.db", pd);
			//下载结束 关闭pd,但是它可以放这,虽然操作了界面显示 ,不过底层已经处理过了,它是先交给主线程处理的。
			pd.dismiss();
//						Toast.makeText(AtoolsActivity.this, "下载成功", 0).show();
//						Intent intent = new Intent(AtoolsActivity.this,QueryNumberActivity.class);
//						startActivity(intent);
			Message msg = new Message();
			msg.what = SUCCESS;
			handler.sendMessage(msg);
		} catch (Exception e) {
			e.printStackTrace();
			pd.dismiss();
			//你把显示提示信息放在这,必死无疑。因为你在子线程里面想要改变界面 
//						
			Message msg = new Message();
			msg.what = ERROR;
			handler.sendMessage(msg);
		}
	};
	
}.start();


左右晃动的动画(安卓DEMO里面的示例,我应该把安卓DEMO里面的示例看过一遍):
sharke.xml.
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:fromXDelta="0"
    android:interpolator="@anim/cycle_7"
    android:toXDelta="10" />
cycle_7.xml---也就是说它可以左右摇动7次。
<cycleInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
    android:cycles="7" />
SDK对Interpolator的描述是:
An interpolator defines the rate of change of an animation.
 This allows the basic animation effects (alpha, scale, translate, rotate)
 to be accelerated, decelerated, repeated, etc。简而言之Interpolator就是一个“变化率”,
 一个基本动画的“变化率”。
 比如:从A到B的一个平移动画,移动,当然后速度的快慢,
 那么从A到B可以是匀速、匀加速、匀减速、变速完成这段距离。
 假设距离为S,时间为t,速度为v,都知道S=v*t。	
	
	




1.手机号码 11位  13 15 18 + 9位数字
135 xxxx xxxx
136 xx
^1[3458]\d{9}$
这个就是用来匹配手机的,开头为1,第二位为3458任意一位,后面跟九个整数。
在JAVA中这些\要转义一下。
String pattern = "^1[3458]\\d{9}$";	
	
2.固定电话 
7位 8位 
本地电话 


10位 3位区号 +7位的电话号码
11位 4位区号 + 7位的电话号码 3位的区号 +8位的电话号码
12位 4位区号 +8位的电话号码 



动态获取别人手机号码归属地:
1.必须要有别人程序的源代码.
2.不修改别人源代码, 判断获取当前手机状态, 呼叫状态显示出来号码的归属地 
第一件事情:判断手机的状态
创建一个android下的服务 , 长期后台运行,不容易被系统回收.
第二件事情:得到电话号码归属地 显示到手机窗体.
   
其实这种是在后台开了一个服务,后台一直监控着通话状态,如果出现接通的时间就把
那个桌面的小窗体显示出来。QQ,360,金山都是这样做的。

Registers a listener object to receive notification of changes in specified telephony states. 

To register a listener, pass a PhoneStateListener and specify at least one telephony state of
 interest in the events argument. At registration, and when a specified telephony state changes,
 the telephony manager invokes the appropriate callback method on the listener object and passes 
 the current (udpated) values. 

To unregister a listener, pass the listener object and set the events argument to LISTEN_NONE (0).


在Service里面也能打印出来
Toast.makeText(getApplicationContext(), address + "address", 1).show();


在后台看服务也可以看到图标的,这个图标就是service的图标 。

其实那些安全的浮窗一样的图标,其实跟Toast差不多,所以我们可以仿写一个图标 。
看看Toast的源代码 。
太神奇了,往WindowsManager上绑定一个View即可。
//得到桌面管理对象
WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
windowManager.addView(tv, params);
通过WindowManager这个对象可以把任何View放到桌面上,太强大了吧。

选择桌面显示的View的风格。



ImageView一些东西?src background ScaleType  区别?
其实ImageView与HTML下的DIV一样,其实所有的控件都可以看成HTML下的
DIV,你设置个SRC只是把它内部显示的那一部分填充了,所以有了padding
这个属性,如果你填写background把整个都填充了。
而ScaleType
  ScaleType的值分别代表的意义: ImageView是Android中的基础图片显示控件,该控件有个重要的属性是ScaleType,该属性用以表示显示图片的方式,共有8种取值

  ScaleType.CENTER::图片大小为原始大小,如果图片大小大于ImageView控件,则截取图片中间部分,若小于,则直接将图片居中显示。

  ScaleType.CENTER_CROP:将图片等比例缩放,让图像的短边与ImageView的边长度相同,即不能留有空白,缩放后截取中间部分进行显示。

  ScaleType.CENTER_INSIDE:将图片大小大于ImageView的图片进行等比例缩小,直到整幅图能够居中显示在ImageView中,小于ImageView的图片不变,直接居中显示。

  ScaleType.FIT_CENTER:ImageView的默认状态,大图等比例缩小,使整幅图能够居中显示在ImageView中,小图等比例放大,同样要整体居中显示在ImageView中。

  ScaleType.FIT_END:缩放方式同FIT_CENTER,只是将图片显示在右方或下方,而不是居中。

  ScaleType.FIT_START:缩放方式同FIT_CENTER,只是将图片显示在左方或上方,而不是居中。

  ScaleType.FIT_XY:将图片非等比例缩放到大小与ImageView相同。即填充整个ImageView.

  ScaleType.MATRIX:是根据一个3x3的矩阵对其中图片进行缩放


任何一个View都有一个叫做layout的方法。非常好用。
tv_drag_view.layout(tv_drag_view.getLeft(), 260, tv_drag_view.getRight(), 280);
l Left position, relative to parent
t Top position, relative to parent
r Right position, relative to parent
b Bottom position, relative to parent

//为布局中的某个控件显式指定其位置。
android.widget.RelativeLayout.LayoutParams layoutParams = (android.widget.RelativeLayout.LayoutParams) iv_drag_view.getLayoutParams();
layoutParams.leftMargin = x;
layoutParams.topMargin = y;
iv_drag_view.setLayoutParams(layoutParams);


注意:Service也继承了Context,
Service  extends ContextWrapper extends Context.
四大组件中两个组件都有继承Context,另外两个比较独立没有继承。

面试题:
点击和触摸的区别是什么?

点击: 一组动作的集合(分为三步) 手指按下着按钮 手指要在按钮停留一段时间 手指离开按钮,又根据停留的长短
有setOnclick 和 setOnLongClick

触摸: 手指一挨着屏幕 手指移动 手指离开屏幕

又有一个惊天的东西,你在onCreate里面执行一些关于界面的操作,可能 
这个时间这个界面并没有生成,很可能那个VIEW在生成的过程中,所以这时间
你就要对它的界面做出改变肯定可能会出问题。所以你可以在onResum()方法中,
表示它已经生成了,并且获取焦点了。

改变activity的背景色。就可以把它做成半透明的效果。
在布局文件里面把整个布局的背景色调制了android:background="#cc000000"
就成了半透明效果。其实一个activity就相当于一个页面或者一个DIV.

响一声电话:在TelephonyManager.CALL_STATE_RINGING://铃响时间
获取当前系统时间,然后在TelephonyManager.CALL_STATE_IDLE://空闲
时间获取当前系统时间,两个相减,如果小于多少秒就认为是响一声电话。

操,又发个自己不知道,原来手机那些可以直接点击的文字,不是一个TextView绑定的
的监听事件,而是一个Button加上了背景色,操 ,太坑爹了。

为什么ListView在拖动的时间是黑色,而静止时间是自己的颜色是因为
ListView的缓存。只需一个配置即可。在这个ListView里面加上它即可。
android:cacheColorHint="@android:color/transparent"

ArrayAdapter对数据做了缓存,不能被那个方法及时更新。所以还是要自定义
Adapter.

上下文菜单 。菜单有三种。

execSQL()用法。
Execute a single SQL statement that is not a query. 
For example, CREATE TABLE, DELETE, INSERT, etc.
Multiple statements separated by ;s are not supported. it takes a write lock。

想要查询用rawQuery();

给按钮加个背景,是个State List Selector选择器。果然不一样了,跟一文本一样。
<Button 
	android:id="@+id/bt_add_black_number"
	android:layout_width="wrap_content"
	android:layout_height="wrap_content"
	android:layout_marginLeft="20dip"
	android:background="@drawable/button_selector"
	android:text="添加"
	android:textColor="#FFF8F8F8"
	android:textSize="20sp"
	/>

//忘记整这句话,下面东西全部空针异常
setContentView(R.layout.call_sms_safe);

最厉害的,我们在ListView里添加过以后,想要异步刷新,
即页面不改变,但是数据改变了。其实就是安卓 中的ajax。
dao.insert(numString);
//此时你肯定想要通知ListView刷新数据。
// 让数据适配器通知listview更新数据 ,相当于异步 刷新 。
numbers = dao.findAll();	//你也要先得到最新的数据。
adapter.notifyDataSetChanged();
Notifies the attached View that the underlying data has been changed
and it should refresh itself.


上下文菜单 :
一、注册
// 给listview注册上下文菜单
registerForContextMenu(lv_call_sms_safe);
二、配置文件
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
	<item android:id="@+id/update_number" android:title="更改黑名单号码"/>
	<item android:id="@+id/deltel_number" android:title="删除黑名单号码"/>           
</menu>
三、覆盖方法
/**
 * 创建上下文菜单 
 */
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
		ContextMenuInfo menuInfo) {
	super.onCreateContextMenu(menu, v, menuInfo);
	//其实这个是获得menu的那个充气的东西,与View略有不同
	MenuInflater inflater = getMenuInflater();
	//把这个布局文件的View给吹起来
	inflater.inflate(R.menu.context_menu, menu);
}
/**
 * 为下下文菜单写监听事件
 */
@Override
public boolean onContextItemSelected(MenuItem item) {
	AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
	switch (item.getItemId()) {
	case R.id.update_number:
		
		break;

	case R.id.deltel_number:
		//当前条目的ID。
		int id = (int) info.id;
		String num = numbers.get(id);
		dao.delete(num);
		//重新获取新的代码 
		numbers = dao.findAll();
		//通知最新的
		adapter.notifyDataSetChanged();
		break;
	}
	
	return false;
}





抱歉!评论已关闭.