当前位置:  编程技术>移动开发
本页文章导读:
    ▪高德map-绘制个人历史位置路线        高德地图-绘制个人历史位置路线思路:将当前个人位置(经纬度信息)存储到手机数据库(SQLITE)中,然后遍历数据库中的所有位置信息,并绘制到MAP图层上。 1.数据库帮助类: package com.ex.........
    ▪ java.util.ConcurrentModificationException-What it means        java.util.ConcurrentModificationException--What it means[Symptom from logcat] 11-26 22:02:37.859   421   487 D ConnectivityService: ConnectivityChange for mobile: DISCONNECTED/DISCONNECTED 11-26 22:02:37.859   421   682 D NetdConnector: RMV &l.........
    ▪ 手机短信年满二十 不是年轻是垂暮       手机短信年满二十 不是年轻是迟暮 它帮助拯救了无数生命,也曾毁灭婚姻,创造了一种新的语言,并为移动运营商创造数十亿美元利润。不过智能手机和数据服务的崛起使得免费短信服务出.........

[1]高德map-绘制个人历史位置路线
    来源: 互联网  发布时间: 2014-02-18
高德地图-绘制个人历史位置路线

思路:将当前个人位置(经纬度信息)存储到手机数据库(SQLITE)中,然后遍历数据库中的所有位置信息,并绘制到MAP图层上。


1.数据库帮助类:

package com.example.touchpoint;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class MysqliteHelper extends SQLiteOpenHelper{


	private static final String DATABASE_NAME = "my.db";
	private static final int DATABASE_VERSION = 1;
	
	public static final String COLUMN_ID = "_id";	//必须的
	public static final String COLUMN_LATITUDE = "latitude";
	public static final String COLUMN_LONGITUDE = "longitude";
	public static final String COLUMN_UPLOAD_TIME = "upload_time";	//暂时没用
	
	
	public static final String[] allColumns = {COLUMN_ID,COLUMN_LATITUDE,COLUMN_LONGITUDE};
	
	private static final String CREATE_TABLE = "create table if not exists routlist"
											 + "("
											 + COLUMN_ID + " integer primary key autoincrement, "
											 + COLUMN_LATITUDE + " REAL not null, "
											 + COLUMN_LONGITUDE + " REAL not null "
											 + ");";
	
	public MysqliteHelper(Context context) {
		super(context, DATABASE_NAME, null, DATABASE_VERSION);
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
		Log.d("CREATE_TABLE",CREATE_TABLE);
		db.execSQL(CREATE_TABLE);
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		db.execSQL("drop table " + CREATE_TABLE);
		onCreate(db);
	}
}

2.数据库DAO

package com.example.touchpoint;

import java.util.ArrayList;
import java.util.List;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

public class SqliteDAO {

	private SQLiteDatabase db;
	private MysqliteHelper helper;
	
	public SqliteDAO(Context context) {
		helper = new MysqliteHelper(context);
	}
	
	public void open() {
		db = helper.getWritableDatabase();
	}
	
	public void close() {
		helper.close();
	}
	public void writePositionToDB(double latitude,double longitude) {
		ContentValues values = new ContentValues();
		values.put(MysqliteHelper.COLUMN_LATITUDE, latitude);
		values.put(MysqliteHelper.COLUMN_LONGITUDE, longitude);
		db.insert("routlist", null, values);
	}

	public List<LocationPoint> getAllPoints() {
		List<LocationPoint> points = new ArrayList<LocationPoint>();

		Cursor cursor = db.query("routlist", MysqliteHelper.allColumns, null, null,
				null, null, null);

		cursor.moveToFirst();
		while (!cursor.isAfterLast()) {
			LocationPoint point = cursorToPoint(cursor);
			points.add(point);
			cursor.moveToNext();
		}
		// 记得关闭cursor对象
		cursor.close();
		return points;
	}
	
	private LocationPoint cursorToPoint(Cursor cursor) {
		LocationPoint point = new LocationPoint();
		point.set_id(cursor.getLong(0));
		point.setLatitude(cursor.getDouble(1));
		point.setLongitutde(cursor.getDouble(2));
		Log.d("route",point.toString());
		return point;
	}
}

3.POJO类:

package com.example.touchpoint;

public class LocationPoint {

	private long _id;
	private double latitude;
	private double longitutde;

	public long get_id() {
		return _id;
	}

	public void set_id(long _id) {
		this._id = _id;
	}

	public double getLatitude() {
		return latitude;
	}

	public void setLatitude(double latitude) {
		this.latitude = latitude;
	}

	public double getLongitutde() {
		return longitutde;
	}

	public void setLongitutde(double longitutde) {
		this.longitutde = longitutde;
	}

	@Override
	public String toString() {
		return "LocationPoint [_id=" + _id + ", latitude=" + latitude
				+ ", longitutde=" + longitutde + "]";
	}
}

4.ItemizedOverlay类

package com.example.touchpoint;

import java.util.ArrayList;
import java.util.List;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.util.Log;

import com.amap.mapapi.core.GeoPoint;
import com.amap.mapapi.core.OverlayItem;
import com.amap.mapapi.map.ItemizedOverlay;
import com.amap.mapapi.map.MapView;
import com.amap.mapapi.map.Projection;

public class RouteItemizedOverlay extends ItemizedOverlay<OverlayItem>{

	private List<OverlayItem> list = new ArrayList<OverlayItem>();
	
	public RouteItemizedOverlay(Drawable d) {
		super(boundCenterBottom(d));		
	}

	@Override
	protected OverlayItem createItem(int id) {
		return list.get(id);
	}

	@Override
	public int size() {
		return list.size();

	}
	
	@Override
	public void draw(Canvas canvas, MapView mapView, boolean shadow) {


		Projection proj = mapView.getProjection();
		Path path = new Path();
		Paint paint = new Paint();
		paint.setAntiAlias(true);  
        paint.setColor(Color.BLUE);  
        paint.setStyle(Paint.Style.STROKE);  
        paint.setStrokeWidth(3);  
		
		for (int i = 0; i < this.size(); i++) {
			OverlayItem item = (OverlayItem)createItem(i);
			GeoPoint gp = item.getPoint();
			Log.d("aa",gp.getLatitudeE6() +" " + gp.getLongitudeE6());
			Point mPoint = new Point();
			proj.toPixels(gp, mPoint);

			if(i == 0) {
				path.moveTo(mPoint.x, mPoint.y);
				Log.d("path","[" + mPoint.x + "," + mPoint.y+ "]");
			}else{
				path.lineTo(mPoint.x, mPoint.y);
				Log.d("path","[" + mPoint.x + "," + mPoint.y+ "]");
			}
			//canvas.drawText("ca", mPoint.x, mPoint.y, new Paint());
		}
		path.close();

		canvas.drawPath(path, paint);

		super.draw(canvas, mapView, shadow);
	}
	public void addMyRoute(List<LocationPoint> points) {

		for(LocationPoint point : points) {
				GeoPoint gp = new GeoPoint((int)(point.getLatitude()*1E6),(int)(point.getLongitutde()*1E6));
				OverlayItem myItem = new OverlayItem(gp, "title", "snippet");
				list.add(myItem);
				Log.d("add","add an item");
				populate();
		}

	}

}

5.MainActivity类:

package com.example.touchpoint;

import java.util.List;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.location.LocationListener;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;

import com.amap.mapapi.core.GeoPoint;
import com.amap.mapapi.location.LocationManagerProxy;
import com.amap.mapapi.location.LocationProviderProxy;
import com.amap.mapapi.map.MapActivity;
import com.amap.mapapi.map.MapController;
import com.amap.mapapi.map.MapView;
import com.amap.mapapi.map.MyLocationOverlay;
import com.amap.mapapi.map.Overlay;
import com.amap.mapapi.map.Projection;

public class MainActivity extends MapActivity implements LocationListener {

	private MapView mMapView;

	private MapController controller;

	private List<Overlay> mapOverlayList;

	private LocationManagerProxy locationProxy;

	private SqliteDAO dao;

	private RouteItemizedOverlay routeOverlay;
	
	private MyOverlay overlay;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		mMapView = (MapView) findViewById(R.id.main_mapView);
		mMapView.setBuiltInZoomControls(true); // 开启缩放控件

		mMapView.setSatellite(true); // 设置为卫星模式

		controller = mMapView.getController();

		controller.setZoom(3);

		mapOverlayList = mMapView.getOverlays();

		locationProxy = LocationManagerProxy.getInstance(this);

		Drawable d = getResources().getDrawable(R.drawable.new_func_dot);

		routeOverlay = new RouteItemizedOverlay(d);

		dao = new SqliteDAO(this);

	}

	@Override
	protected void onPause() {
		locationProxy.removeUpdates(this);
		dao.close();
		super.onPause();
	}

	@Override
	protected void onResume() {
		locationProxy.requestLocationUpdates(
				LocationProviderProxy.MapABCNetwork, 0, 0, this);
		dao.open();
		super.onResume();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.activity_main, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.showroute:
			showRoutlist();
			break;
		case R.id.closeroute:
			break;
		default:
			break;
		}
		return super.onOptionsItemSelected(item);
	}

	private void showRoutlist() {
		mapOverlayList.remove(overlay);
		locationProxy.removeUpdates(this); // 取消位置监听(数据库不会有更新)

		routeOverlay.addMyRoute(dao.getAllPoints());

		mapOverlayList.add(routeOverlay);
	}

	public void closeRoute() {
		mapOverlayList.clear(); // 清空路线
		Location last = locationProxy
				.getLastKnownLocation(LocationProviderProxy.MapABCNetwork);

		mapOverlayList.add(new MyOverlay(this, new GeoPoint((int) (last
				.getLatitude() * 1E6), (int) (last.getLongitude() * 1E6))));
		locationProxy.requestLocationUpdates(LocationManagerProxy.GPS_PROVIDER,
				0, 0, this); // 开始监听位置变化
	}

	public void onLocationChanged(Location location) {
		mapOverlayList.clear();
		if (location != null) {
			double latitude = location.getLatitude();
			double longitude = location.getLongitude();

			dao.writePositionToDB(latitude, longitude); // 写进数据库

			GeoPoint gp = new GeoPoint((int) (latitude * 1E6),
					(int) (longitude * 1E6));
		    overlay = new MyOverlay(this, gp);
			mapOverlayList.add(overlay);
		}
	}

	public void onStatusChanged(String provider, int status, Bundle extras) {

	}

	public void onProviderEnabled(String provider) {

	}

	public void onProviderDisabled(String provider) {

	}

}

class MyOverlay extends Overlay {

	private Context mContext;
	private GeoPoint gp;
	private Bitmap bitmap;

	public MyOverlay(Context mContext, GeoPoint gp) {
		this.mContext = mContext;
		this.gp = gp;
		bitmap = BitmapFactory.decodeResource(mContext.getResources(),
				R.drawable.new_func_dot);
	}

	@Override
	public void draw(Canvas canvas, MapView mapView, boolean shadow) {
		Projection proj = mapView.getProjection();
		Point mPoint = proj.toPixels(gp, null);
		canvas.drawBitmap(bitmap, mPoint.x, mPoint.y, null);
		super.draw(canvas, mapView, shadow);
	}

}

用到的图片:

项目文件在:http://download.csdn.net/detail/czjuttsw/4861690


    
[2] java.util.ConcurrentModificationException-What it means
    来源: 互联网  发布时间: 2014-02-18
java.util.ConcurrentModificationException--What it means

[Symptom from logcat]
11-26 22:02:37.859   421   487 D ConnectivityService: ConnectivityChange for mobile: DISCONNECTED/DISCONNECTED
11-26 22:02:37.859   421   682 D NetdConnector: RMV <- {200 39372 Route added to default table}
11-26 22:02:37.859   421   484 D StateMachine: handleMessage: E msg.what=131085
11-26 22:02:37.859   421   484 D StateMachine: processMsg: DriverUnloadedState
11-26 22:02:37.859   421   484 D WifiStateMachine: DriverUnloadedState{ what=131085 when=-1ms }
11-26 22:02:37.859   421   487 D ConnectivityService: Attempting to switch to WIFI
11-26 22:02:37.869   421   484 D StateMachine: processMsg: DefaultState
11-26 22:02:37.869   421   484 D WifiStateMachine: DefaultState{ what=131085 when=-5ms }
11-26 22:02:37.869   421   484 D StateMachine: handleMessage: X
11-26 22:02:37.869   421   484 D StateMachine: handleMessage: E msg.what=131147
11-26 22:02:37.869   421   484 D StateMachine: processMsg: DriverUnloadedState
11-26 22:02:37.869   421   484 D WifiStateMachine: DriverUnloadedState{ what=131147 when=-8ms }
11-26 22:02:37.869   421   484 D StateMachine: processMsg: DefaultState
11-26 22:02:37.869   421   484 D WifiStateMachine: DefaultState{ what=131147 when=-11ms }
11-26 22:02:37.869   421   484 D StateMachine: handleMessage: X
11-26 22:02:37.869   421   487 D ConnectivityService: Attempting to switch to BLUETOOTH_TETHER
11-26 22:02:37.869   421   487 D ConnectivityService: handleConnectivityChange: changed linkProperty[0]: doReset=true resetMask=3
11-26 22:02:37.869   421   487 D ConnectivityService:   curLp=InterfaceName: rmnet0 LinkAddresses: [192.168.35.117/30,] Routes: [0.0.0.0/0 -> 192.168.35.118,] DnsAddresses: [192.168.212.10,]
11-26 22:02:37.869   421   487 D ConnectivityService:   newLp= null
11-26 22:02:37.879   421   682 D ConnectivityService: Adding 192.168.23.5/32 -> 172.11.208.57 for interface rmnet1

11-26 22:02:37.919   499   499 D StatusBar.NetworkController: onDataConnectionStateChanged: state=0 type=0
11-26 22:02:37.929   499   499 E StatusBar.NetworkController: updateDataNetType NETWORK_TYPE_UNKNOWN
11-26 22:02:38.069   421   487 W dalvikvm: threadid=44: thread exiting with uncaught exception (group=0x40c07498)

11-26 22:02:38.149   421   487 E AndroidRuntime: *** FATAL EXCEPTION IN SYSTEM PROCESS: ConnectivityServiceThread
11-26 22:02:38.149   421   487 E AndroidRuntime: java.util.ConcurrentModificationException
11-26 22:02:38.149   421   487 E AndroidRuntime:  at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:569)
11-26 22:02:38.149   421   487 E AndroidRuntime:  at com.android.server.ConnectivityService.modifyRoute(ConnectivityService.java:1553)
11-26 22:02:38.149   421   487 E AndroidRuntime:  at com.android.server.ConnectivityService.modifyRoute(ConnectivityService.java:1528)
11-26 22:02:38.149   421   487 E AndroidRuntime:  at com.android.server.ConnectivityService.removeRoute(ConnectivityService.java:1476)
11-26 22:02:38.149   421   487 E AndroidRuntime:  at com.android.server.ConnectivityService.updateRoutes(ConnectivityService.java:2252)
11-26 22:02:38.149   421   487 E AndroidRuntime:  at com.android.server.ConnectivityService.handleConnectivityChange(ConnectivityService.java:2179)
11-26 22:02:38.149   421   487 E AndroidRuntime:  at com.android.server.ConnectivityService.handleDisconnect(ConnectivityService.java:1824)
11-26 22:02:38.149   421   487 E AndroidRuntime:  at com.android.server.ConnectivityService.access$1100(ConnectivityService.java:128)
11-26 22:02:38.149   421   487 E AndroidRuntime:  at com.android.server.ConnectivityService$MyHandler.handleMessage(ConnectivityService.java:2687)
11-26 22:02:38.149   421   487 E AndroidRuntime:  at android.os.Handler.dispatchMessage(Handler.java:99)
11-26 22:02:38.149   421   487 E AndroidRuntime:  at android.os.Looper.loop(Looper.java:137)
11-26 22:02:38.149   421   487 E AndroidRuntime:  at android.os.HandlerThread.run(HandlerThread.java:60)
11-26 22:02:38.189   421   487 W DropBoxManagerService: Dropping: system_server_crash (1098 > 0 bytes)
11-26 22:02:38.209   421   487 E ActivityManager: handleApplicationCrash happeded!! and crash level = 2, trigger panic!!
11-26 22:02:38.209   421   487 E ActivityManager: TriggerKernelPanic IN

[Analysis]
modifyRoute(...) @ ConnectivityService.java
1505    private boolean modifyRoute(String ifaceName, LinkProperties lp, RouteInfo r, int cycleCount,
1506            boolean doAdd, boolean toDefaultTable) {
1507        if ((ifaceName == null) || (lp == null) || (r == null)) {
1508            if (DBG) log("modifyRoute got unexpected null: " + ifaceName + ", " + lp + ", " + r);
1509            return false;
1510        }
1511
1512        if (cycleCount > MAX_HOSTROUTE_CYCLE_COUNT) {
1513            loge("Error modifying route - too much recursion");
1514            return false;
1515        }
1516
1517        if (r.isHostRoute() == false) {
1518            RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getRoutes(), r.getGateway());
1519            if (bestRoute != null) {
1520                if (bestRoute.getGateway().equals(r.getGateway())) {
1521                    // if there is no better route, add the implied hostroute for our gateway
1522                    bestRoute = RouteInfo.makeHostRoute(r.getGateway());
1523                } else {
1524                    // if we will connect to our gateway through another route, add a direct
1525                    // route to it's gateway
1526                    bestRoute = RouteInfo.makeHostRoute(r.getGateway(), bestRoute.getGateway());
1527                }
1528                modifyRoute(ifaceName, lp, bestRoute, cycleCount+1, doAdd, toDefaultTable);
1529            }
1530        }
1531        if (doAdd) {
1532            if (VDBG) log("Adding " + r + " for interface " + ifaceName);  ----- logout line "11-26 22:02:37.879   421   682 D ConnectivityService: Adding 192.168.23.5/32 -> 172.11.208.57 for interface rmnet1"
1533            try {
1534                if (toDefaultTable) {
1535                    mAddedRoutes.add(r);  // only track default table - only one apps can effect
1536                    if (VDBG) log("Routes in main table - [ " + mAddedRoutes + " ]");
1537                    mNetd.addRoute(ifaceName, r);
1538                } else {
1539                    mNetd.addSecondaryRoute(ifaceName, r);
1540                }
1541            } catch (Exception e) {
1542                // never crash - catch them all
1543                if (DBG) loge("Exception trying to add a route: " + e);
1544                return false;
1545            }
1546        } else {
1547            // if we remove this one and there are no more like it, then refcount==0 and
1548            // we can remove it from the table
1549            if (toDefaultTable) {
1550                // modified begin
1551                //mAddedRoutes.remove(r);
1552                for (Iterator<RouteInfo> it = mAddedRoutes.iterator(); it.hasNext();) {
1553                    RouteInfo thisRI = it.next();
1554                    if ( thisRI.equals(r) ) {
1555                        it.remove();
1556                    }
1557                }
1558                // modified end
1559                if (VDBG) log("Routes in main table - [ " + mAddedRoutes + " ]");
1560                if (mAddedRoutes.contains(r) == false) {
1561                    if (VDBG) log("Removing " + r + " for interface " + ifaceName);
1562                    try {
1563                        mNetd.removeRoute(ifaceName, r);
1564                    } catch (Exception e) {
1565                        // never crash - catch them all
1566                        if (VDBG) loge("Exception trying to remove a route: " + e);
1567                        return false;
1568                    }
1569                } else {
1570                    if (VDBG) log("not removing " + r + " as it's still in use");
1571                }
1572            } else {
1573                if (VDBG) log("Removing " + r + " for interface " + ifaceName);
1574                try {
1575                    mNetd.removeSecondaryRoute(ifaceName, r);
1576                } catch (Exception e) {
1577                    // never crash - catch them all
1578                    if (VDBG) loge("Exception trying to remove a route: " + e);
1579                    return false;
1580                }
1581            }
1582        }
1583        return true;
1584    }

We can see that adding a new item into mAddedRoutes in thread 682 and remove a item from mAddedRoutes in thread 487 at same time.

[JRE document Reference]
public class ConcurrentModificationException
extends RuntimeException
This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible.

For example, it is not generally permssible for one thread to modify a Collection while another thread is iterating over it. In general, the results of the iteration are undefined under these circumstances. Some Iterator implementations (including those of all the collection implementations provided by the JRE) may choose to throw this exception if this behavior is detected. Iterators that do this are known as fail-fast iterators, as they fail quickly and cleanly, rather that risking arbitrary, non-deterministic behavior at an undetermined time in the future.

Note that this exception does not always indicate that an object has been concurrently modified by a different thread. If a single thread issues a sequence of method invocations that violates the contract of an object, the object may throw this exception. For example, if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will thow this exception.
Note that fail-fast behavior cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast operations throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: ConcurrentModificationException should be used only to detect bugs.

The modification status of a container will be recored during one iterator of this container being initialized.
Any modification that is not operated by that iterator of this container will lead to a "java.util.ConcurrentModificationException" if the iterator is still valid and active.

[Reference solution]
Adding a synchronization mechanism for mAddedRoutes such as synchronized(mAddedRoutes) to keep its modification thread-safe.


    
[3] 手机短信年满二十 不是年轻是垂暮
    来源: 互联网  发布时间: 2014-02-18
手机短信年满二十 不是年轻是迟暮

它帮助拯救了无数生命,也曾毁灭婚姻,创造了一种新的语言,并为移动运营商创造数十亿美元利润。不过智能手机和数据服务的崛起使得免费短信服务出现,手机短信面临衰退。

北京时间12月3日消息,英国《卫报》日前撰文回顾了短信服务20年的发展,并指出在智能手机时代,随着免费短信服务出现,手机短信不可避免地面临衰退。

以下为文章主要内容:

它帮助拯救了无数生命,也曾毁灭婚姻,创造了一种新的语言并为移动运营商创造数十亿美元利润。随着手机短信庆祝自己的第20个生日,有人疑问在智能手机和无限量网络数据的世界,手机短信还能生存多长时间。

短信发送的数量逐年大幅增加,不过有迹象表明在几个国家和地区已经达到顶峰,包括西班牙、荷兰、芬兰、香港和澳大利亚。新一代的用户曾经使用短信,但是现在免费使用WhatsApp或者BlackBerry Messenger等用户数据服务。

Enders Analysis 公司电信分析师本尼迪克特·埃文斯表示:“现在有很多这样服务,我已经统计了有25种,据报告账户总数已经达到25亿,不过很多这些账户都是重复的。可能有10项服务拥有超过1亿用户,BBM并不在其中,只有6000万用户。”

历 史上发送的第一条短信是在1992年12月3日,当时一位22岁的英国工程师尼尔·帕普沃思(Neil Papworth)利用自己的电脑向沃达丰公司经理理查德·贾维斯(Richard Jarvis)发送短信,祝福后者“圣诞节快乐”,当时接收短信的手机是欧比特901。帕普沃思并没有收到回复,因为当时手机并不能发送短信。我们需要等 到诺基亚在1993年推出的首款手机。

第一批短信都是免费的,只可以在同一个网络的用户间发送,但是在1994年,沃达丰(当时英国2家移动网络之一)推出一个股价提醒系统。Tegic系统(即T9短信输入系统)在1995年推出,大大缩短了文字输入的时间,意味着短信业务可以快速起飞。

商 业服务很快跟随而至,尽管这些服务起初是免费的——因为运营商并没有想到如何进行收费,但是随着短信数量大幅增加,他们很快意识到可以从中赚钱。在 2001年2月,英国每个月的短信数量达到10亿条,如果按照标准的每条短信10便士计算,这项业务每个月能带来约1亿英镑收入。

一条短信的数据流量非常小,只有128字节。按照同样的收费计算,650M的音乐CE将收费超过6万英镑。

在同一年,短信成为了人们生活的重要部分,14名英国游客在巴厘岛外的龙目海峡(Lombok Strait)搁浅,好在一位游客发短信给自己在英格兰的男友,他们才能全部获救;一位登山者凭借一条短信联系到了登山救援队,从而安全获救。

由于短信最多只能发动160个字母并且通过数字键盘输入单词较为耗费时间,因而“短信文”( Text language)快速出现。"l8r"、"gr8" 和"b4"等缩写很快令大人们迷糊,他们抱怨说孩子们已经丧失了正确拼写单词的能力。

到 2003年,改卷人员对于考生答案中使用“短信文”的问题越来越担忧:一位13岁的女孩以短信缩写的方式写了一篇文章,其中她写道“My smmr hols wr CWOT. B4, we used 2go2 NY 2C my bro, his GF & thr 3 :- kids FTF. ILNY, it's a gr8 plc”,实际内容为:“My summer holidays were a complete waste of time. Before, we used to go to New York to see my brother, his girlfriend and their three (!) kids face to face. I love New York, it's a great place”(我的暑假过得非常浪费。之前,我们通常是去纽约看望哥哥、他女朋友还有他们三个孩子。我喜欢纽约,那是个非常不错的地方。)

不过,现在短信比英语面临更大的威胁。智能手机和数据服务的崛起意味着发送数据的价格大幅降低,这已经导致免费服务的出现,甚至在你的手机没有数据的情况下你也可以发送数据。

今年1月,芬兰移动网络Sonera报告称,2011年圣诞节前夕发送短信的数量为850万条,低于上一年的1090万条。在香港,短信发送数量减少14%。

不过这并不意味着短信将消失,或者移动运营商将突然破产。短信已经带来超过5000亿美元收入,并且市场预测在未来7年仍然产生1万亿元美元,因为人们在非洲和印度用短信进行移动银行业务,此外其他地方也使用短信进行慈善捐赠和政治捐献。

埃文斯表示,随着短信数量减少,运营商将调整他们的价格模式。“他们将开始收取更多费用以传输更多数据。传送500M数据的费用超过传输500分钟语音通话的费用。因此他们将重新调整价格。”

但他表示不同设备间发送短信的主意将继续保持:“Twitter被认为是一项短信服务,这就是为什么每条Twitter消息都这么短。短信发送的机制将改变,不过人们将发现相互间发送短信变得更便利。”

时间线

1992年 首条短信发出

1995年 T9系统推出,使短信输入更快捷

2001年 英国一个月的短信量达到10亿条

2001年 短信用于帮助组织推翻菲律宾总统约瑟夫·埃斯特拉达(Joseph Estrada)的示威活动。

2002年 一项名为Text2TV的服务称可以让你向电视机发短信并通过你的遥控器进行回复。但是这项服务并没有得到大幅应用

2003年 球星大卫·贝克汉姆(David Beckham)向自己的个人助理丽贝卡·卢斯(Rebecca Loos)发送一系列暧昧短信;这些短信之后被公开,几乎导致贝克汉姆的婚姻终结。

2004年 托尼·布莱尔(Tony Blair)参加一次直播的短信互动聊天

2005年 欧洲歌唱大赛(Eurovision)加入短信投票

2008年 尼尔森报告称,平均每位美国手机用户每月发送和接收短信数量超过打电话数量——357 V 204

2009年 免费短信服务WhatsApp创立。

2011年 芬兰、香港、西班牙和荷兰圣诞节发送短信数量同比下滑

2012年 Ofcom报告称,短信是亲友间日常沟通联系最普遍使用的办法——58%的英国成年人每天至少发一条短信给亲友。

2012 年 丽贝卡·布鲁克斯(Rebekah Brooks)透露戴维·卡梅伦(David Cameron)向她发送签名为“LOL”的短信,因为他认为这意味着“很多爱”(lots of love),但该缩写通常的意思是“放声大笑”(laughing out loud)。


    
最新技术文章:
▪Android开发之登录验证实例教程
▪Android开发之注册登录方法示例
▪Android获取手机SIM卡运营商信息的方法
▪Android实现将已发送的短信写入短信数据库的...
▪Android发送短信功能代码
▪Android根据电话号码获得联系人头像实例代码
▪Android中GPS定位的用法实例
▪Android实现退出时关闭所有Activity的方法
▪Android实现文件的分割和组装
▪Android录音应用实例教程
▪Android双击返回键退出程序的实现方法
▪Android实现侦听电池状态显示、电量及充电动...
▪Android获取当前已连接的wifi信号强度的方法
▪Android实现动态显示或隐藏密码输入框的内容
▪根据USER-AGENT判断手机类型并跳转到相应的app...
▪Android Touch事件分发过程详解
▪Android中实现为TextView添加多个可点击的文本
▪Android程序设计之AIDL实例详解
▪Android显式启动与隐式启动Activity的区别介绍
▪Android按钮单击事件的四种常用写法总结
▪Android消息处理机制Looper和Handler详解
▪Android实现Back功能代码片段总结
▪Android实用的代码片段 常用代码总结
▪Android实现弹出键盘的方法
▪Android中通过view方式获取当前Activity的屏幕截...
▪Android提高之自定义Menu(TabMenu)实现方法
▪Android提高之多方向抽屉实现方法
▪Android提高之MediaPlayer播放网络音频的实现方法...
▪Android提高之MediaPlayer播放网络视频的实现方法...
▪Android提高之手游转电视游戏的模拟操控
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3