*********************************************2012-11-23****************************************************
十一、Content provider内容提供者控件
1、作用:内容提供者为数据共享提供统一接口,也是一个常用的控件
2、配置:
a、创建内容提供者类继承ContentProvider类的,并覆写抽象方法
b、配置ContentProvider,在提供方的应用的AndroidManifest.xml中添加配置
<provider android:name=".UserProvider" (ContentProvider类路径)
android:authorities="com.caiz.android.providers.userProvider" />(ContentProvider的唯一标识uri)
3、uri
content://cn.itcast.provider/person/10
代表含义:scheme(固定)// 主机名或authority /路径(数据)
4、编码实现通过内容提供者给外界程序提供操作数据的接口
a、内容提供者实现类:UserProvider
package caiz.android.dboper;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import caiz.android.dboper.service.DBOpenHelper;
/**
* 内容提供者访问数据库
* @author HuangYucai
*
*/
public class UserProvider extends ContentProvider {
private DBOpenHelper dbOpenHelper;
private static final UriMatcher MATCHER = new UriMatcher(
UriMatcher.NO_MATCH);
private static final int INSERTUSER = 1;
private static final int DELETEUSER = 2;
static {
MATCHER.addURI("com.caiz.android.providers.userProvider", "user",
INSERTUSER);
MATCHER.addURI("com.caiz.android.providers.userProvider", "user/#",
DELETEUSER);
}
@Override
public boolean onCreate() {// 当内容提供者创建时自动调用
dbOpenHelper = new DBOpenHelper(this.getContext());
// TODO Auto-generated method stub
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
Cursor cursor = null;
switch (MATCHER.match(uri)) {
case 1:
cursor = db.query("user", projection, selection, selectionArgs,
null, null, sortOrder);
return cursor;
case 2:
long rowid = ContentUris.parseId(uri);
String where = "uid=" + rowid;
if (selection != null && !"".equals(selection.trim())) {
where = where + " and " + selection;
}
cursor = db.query("user", projection, where, selectionArgs, null,
null, sortOrder);
return cursor;
default:
throw new IllegalArgumentException("The uri'" + uri
+ "' is illegal!");
}
}// 供外部应用查询内容提供者的数据
@Override
public String getType(Uri uri) {// 返回操作数据的类型
// TODO Auto-generated method stub
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {// 供外部应用插入内容提供者的数据
// 判断uri专门类
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
switch (MATCHER.match(uri)) {
case 1:
long rowid = db.insert("user", "uname", values);
Uri insertUri = ContentUris.withAppendedId(uri, rowid);
return insertUri;
default:
throw new IllegalArgumentException("The uri'" + uri
+ "' is illegal!");
}
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {// 供外部应用删除内容提供者的数据
// 判断uri专门类
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
int rowCounts = 0;
switch (MATCHER.match(uri)) {
case 1:
rowCounts = db.delete("user", selection, selectionArgs);
break;
case 2:
long rowid = ContentUris.parseId(uri);
String where = "uid=" + rowid;
if (selection != null && !"".equals(selection.trim())) {
where = where + " and " + selection;
}
rowCounts = db.delete("user", where, selectionArgs);
break;
default:
throw new IllegalArgumentException("The uri'" + uri
+ "' is illegal!");
}
return rowCounts;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {// 供外部应用更新内容提供者的数据
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
int rowCounts = 0;
switch (MATCHER.match(uri)) {
case 1:
rowCounts = db.update("user", values, selection, selectionArgs);
break;
default:
throw new IllegalArgumentException("The uri'" + uri
+ "' is illegal!");
}
return rowCounts;
}
}
b、内容通过者的测试类:ContentProviderTest
package caiz.android.xml.test;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.test.AndroidTestCase;
import android.util.Log;
/**
* 内容提供者测试类
* @author HuangYucai
*
*/
public class ContentProviderTest extends AndroidTestCase {
public void testInsert()throws Exception{//测试添加
Uri uri=Uri.parse("content://com.caiz.android.providers.userProvider/user");
ContentResolver resolver=this.getContext().getContentResolver();
ContentValues values=new ContentValues();
values.put("uname", "tqiongqiong");
values.put("phone", "1523798091");
values.put("amount", "5000001");
resolver.insert(uri, values);
}
public void testDelete()throws Exception{//测试删除
Uri uri=Uri.parse("content://com.caiz.android.providers.userProvider/user/44");
ContentResolver resolver=this.getContext().getContentResolver();
int i=resolver.delete(uri, null, null);
Log.i("ContentProvider", "删除了"+i+"条记录");
}
public void testUpdate()throws Exception{//测试更新
Uri uri=Uri.parse("content://com.caiz.android.providers.userProvider/user/");
ContentResolver resolver=this.getContext().getContentResolver();
ContentValues values=new ContentValues();
values.put("uname", "tangqiongqiong");
values.put("amount", "5000002");
int i=resolver.update(uri, values, "uid=?", new String[]{"45"});
Log.i("ContentProvider", "更新了"+i+"条记录");
}
public void testQueryList()throws Exception{//测试查询列表
Uri uri=Uri.parse("content://com.caiz.android.providers.userProvider/user/");
ContentResolver resolver=this.getContext().getContentResolver();
Cursor cursor= resolver.query(uri, null, "uid>?", new String[]{"20"}, "uid desc");
int num=0;
while(cursor.moveToNext()){
String uname= cursor.getString(cursor.getColumnIndex("UNAME"));
Log.i("ContentProvider", "用户"+(++num)+"的姓名:"+uname);
}
}
public void testQueryById()throws Exception{//测试查询单个
Uri uri=Uri.parse("content://com.caiz.android.providers.userProvider/user/");
ContentResolver resolver=this.getContext().getContentResolver();
Cursor cursor= resolver.query(uri, null, "uid=?", new String[]{"45"}, "uid desc");
if(cursor.moveToNext()){
String uname= cursor.getString(cursor.getColumnIndex("UNAME"));
Log.i("ContentProvider", "id为45的用户姓名是:"+uname);
}
}
}
***********************************************************************************************************
*************************************************2012-11-24************************************************
十一、监听Content provider内容提供者的数据变化
1、作用:两个应用操作使用同一个内容提供者的数据,A应用改变了内容提供者数据,必须通知B应用内容提供者数据
已经改变
A应用---添加数据---》内容提供者---》发出数据变化通知---》B应用(做出响应)
原理:观察者设计模式的应用
2、代码实践:
a、A应用在界面中添加一个按钮,并设置单击事件:
<?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="fill_parent"
android:orientation="vertical" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/bnt"
android:onClick="insert"
/>
</LinearLayout>
public class AAppActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
//点击按钮时执行的插入数据命令
public void insert(View v) {
Uri uri=Uri.parse("content://com.caiz.android.providers.userProvider/user");
ContentResolver resolver =this.getContentResolver();
ContentValues values=new ContentValues();
values.put("uname", "A_App insert CaiZ");
values.put("phone", "123456789");
values.put("amount", "70000");
resolver.insert(uri, values);
}
}
b、在内容提供者应用的添加数据方法中添加内容更新通知
@Override
public Uri insert(Uri uri, ContentValues values) {// 供外部应用插入内容提供者的数据
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
switch (MATCHER.match(uri)) {
case 1:
long rowid = db.insert("user", "uname", values);
Uri insertUri = ContentUris.withAppendedId(uri, rowid);
//设置数据更新通知(对于某个uri)
this.getContext().getContentResolver().notifyChange(uri, null);
return insertUri;
default:
throw new IllegalArgumentException("The uri'" + uri
+ "' is illegal!");
}
}
c、在应用B中添加应用的事件监听处理方法
package com.caiz.android.bapp;
import android.app.Activity;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
public class BAppActivity extends Activity {
/** Called when the activity is first created. */
public static final String TAG = "BApp";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Uri uri = Uri.parse("content://com.caiz.android.providers.userProvider/user");
// 注册内容观察者
this.getContentResolver().registerContentObserver(uri, true,
new UserContentObserver(new Handler()));
}
// 内容观察者内部类(继承观察者内部类)
public class UserContentObserver extends ContentObserver {
//构造方法
public UserContentObserver(Handler handler) {
super(handler);
}
// (覆写)数据改变时候调用的方法
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
Log.i(TAG, "OK=OK");
Uri uri = Uri
.parse("content://com.caiz.android.providers.userProvider/user");
Cursor cursor = getContentResolver().query(uri, null, null, null,
"uid desc limit 1");
if (cursor.moveToFirst()) {// 查询出最新记录并打印出来
String uname = cursor.getString(cursor.getColumnIndex("UNAME"));
Log.i(TAG, "uname=" + uname);
}
}
}
}
***********************************************************************************************************
**********************************************2012-11-25***************************************************
十二、访问和添加通讯录内容
1、作用:有些应用要求访问或添加通讯录操作
2、添加权限,在清单文件中添加读写通讯录的权限:
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
3、代码实现:
/**
* 存取通讯录中信息内容
* @author HuangYucai
*/
public class ContactsTest extends AndroidTestCase {
private String TAG="ContactsTest";
// 测试获取通讯录
public void testGetContacts()throws Exception {
StringBuilder sb=new StringBuilder("DATA:");
Uri uri = Uri.parse("content://com.android.contacts/contacts");
ContentResolver resolver = this.getContext().getContentResolver();
Cursor cursor = resolver.query(uri, new String[] { "_id" }, null, null,
null);
while (cursor.moveToNext()) {
String id=cursor.getString(0);
uri = Uri.parse("content://com.android.contacts/contacts/"+id+"/data");
sb.append("id=").append(id);
resolver = this.getContext().getContentResolver();
Cursor c = resolver.query(uri, new String[] { "data1","data2","mimetype" }, null, null,null);
while(c.moveToNext()){
String type=c.getString(c.getColumnIndex("mimetype"));
String data=c.getString(c.getColumnIndex("data1"));
if(type.equals("vnd.android.cursor.item/name")){
sb.append("name=").append(data);
}
if(type.equals("vnd.android.cursor.item/email_v2")){
sb.append("email=").append(data);
}
if(type.equals("vnd.android.cursor.item/phone_v2")){
sb.append("phone=").append(data);
}
}
}
Log.i(TAG,sb.toString());
}
//测试通过电话号码查询联系人
public void testgetNameByPhone() throws Exception{
StringBuilder sb=new StringBuilder("DATA:");
String number="13533415878";
Uri uri=Uri.parse("content://com.android.contacts/data/phones/filter/"+number);
ContentResolver resolver =this.getContext().getContentResolver();
Cursor cursor=resolver.query(uri, new String[]{"display_name"}, null, null, null);
if(cursor.moveToFirst()){
sb.append("name=").append(cursor.getString(0));
}
Log.i(TAG,sb.toString());
}
//测试通过电话号码查询联系人
public void testAddContacts() throws Exception{
Uri uri=Uri.parse("content://com.android.contacts/raw_contacts/");
ContentResolver resolver =this.getContext().getContentResolver();
ContentValues values =new ContentValues();
long rowid=ContentUris.parseId(resolver.insert(uri, values));
uri=Uri.parse("content://com.android.contacts/data/");
values.put("raw_contact_id", rowid);
values.put("mimetype", "vnd.android.cursor.item/name");
values.put("data2", "黄育才");
resolver.insert(uri, values);
values.clear();
values.put("raw_contact_id", rowid);
values.put("mimetype", "vnd.android.cursor.item/phone_v2");
values.put("data2", "2");
values.put("data1", "12121212");
resolver.insert(uri, values);
values.clear();
values.put("raw_contact_id", rowid);
values.put("mimetype", "vnd.android.cursor.item/email_v2");
values.put("data2", "2");
values.put("data1", "huangyc1210@163.com");
resolver.insert(uri, values);
}
//测试通过电话号码查询联系人(带事务处理的方法)
public void testAddContactsWithTransaction() throws Exception{
ArrayList<ContentProviderOperation> operations =new ArrayList<ContentProviderOperation>();
Uri uri=Uri.parse("content://com.android.contacts/raw_contacts/");
ContentResolver resolver =this.getContext().getContentResolver();
ContentProviderOperation op1=ContentProviderOperation.newInsert(uri)
.withValue("account_name", null)
.build();
operations.add(op1);
uri=Uri.parse("content://com.android.contacts/data/");
ContentProviderOperation op2=ContentProviderOperation.newInsert(uri)
.withValueBackReference("raw_contact_id", 0)
.withValue("mimetype", "vnd.android.cursor.item/name")
.withValue("data2", "2")
.withValue("data1", "刘德华")
.build();
operations.add(op2);
ContentProviderOperation op3=ContentProviderOperation.newInsert(uri)
.withValueBackReference("raw_contact_id", 0)
.withValue("mimetype", "vnd.android.cursor.item/phone_v2")
.withValue("data2", "2")
.withValue("data1", "121212123")
.build();
operations.add(op3);
ContentProviderOperation op4=ContentProviderOperation.newInsert(uri)
.withValueBackReference("raw_contact_id", 0)
.withValue("mimetype", "vnd.android.cursor.item/email_v2")
.withValue("data2", "2")
.withValue("data1", "liudehua@163.com")
.build();
operations.add(op4);
//执行事务方式的保存
resolver.applyBatch("com.android.contacts", operations);
}
}
***********************************************************************************************************
********************************************2012-11-26*****************************************************
十三、网络图片查看器
1、作用:将通过HTTP访问网络图片数据,并将图片数据在android手机应用中显示
2、思路:使用API
ImageView 类 的setImageBitmap(Bitmap bm)
通过URL类 构建一个HttpURLConnection实例
HttpURLConnection 类 getInputStream() 拿到数据流
IO操作把流转换成字节数组
3、实现过程及代码:
a、创建应用的界面,图片显示一般用ImageView控件
b、需要设置访问网络的权限
在清单文件中加入:<uses-permission android:name="android.permission.INTERNET"/>
c、代码:
/**
* 读取网络图片的主类
* @author HuangYucai
*/
public class NetImageActivity extends Activity {
/** Called when the activity is first created. */
private Button bnt;
private ImageView imgview;
private EditText txtEdit;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
txtEdit=(EditText)this.findViewById(R.id.imagepath);
bnt=(Button)this.findViewById(R.id.bnt);
imgview=(ImageView)this.findViewById(R.id.image);
bnt.setOnClickListener(new BntOnclickListener());
}
//单机按钮的事件监听器实现类
public final class BntOnclickListener implements View.OnClickListener{
public void onClick(View v) {
String url=txtEdit.getText().toString().trim();//获取图片的路径
if(url!=null&&!"".equals(url)){
try {
byte[] data = ImageService.getImageDataByUrl(url);//获取图片的字节数组数据
Bitmap bm=BitmapFactory.decodeByteArray(data, 0, data.length);//Bitmap对象
imgview.setImageBitmap(bm);//设置图片显示
} catch (Exception e) {
Toast.makeText(getApplicationContext(), "图片访问失败", Toast.LENGTH_SHORT).show();
}
}else{
Toast.makeText(getApplicationContext(), "请输入图片路径", Toast.LENGTH_SHORT).show();
}
}
}
}
/**
* 读取图片的service类
* @author HuangYucai
*/
public class ImageService {
public static byte[] getImageDataByUrl(String path) throws Exception {
URL url=new URL(path);//根据路径初始化URL对象
HttpURLConnection conn=(HttpURLConnection) url.openConnection();//根据URL获取HttpURLConnection
conn.setConnectTimeout(5000);//设置HttpURLConnection请求时间为5秒
conn.setRequestMethod("GET");//设置HttpURLConnection请求方式为“GET”
if(conn.getResponseCode()==200){//当请求状态为200,即为请求成功时则获取输入流
InputStream inStream=conn.getInputStream();//获取输入流
return StreamTool.readBytes(inStream);//处理输入流
}else{
throw new Exception();
}
}
}
/**
*输入流转换为字节数组的工具类
* @author HuangYucai
*/
public class StreamTool {
public static byte[] readBytes(InputStream inStream) throws Exception {
ByteArrayOutputStream bis=new ByteArrayOutputStream();//字节输出流对象
byte[] buffer=new byte[1024];
int len=0;
while((len=inStream.read(buffer))!=-1){//读到buffer
bis.write(buffer,0,len);//写buffer到字节输出流对象bis
}
return bis.toByteArray();//从内存中拿到然后转为字节数组返回
}
}
4、注意项
在访问本机的url时,一般用http://localhost:8080/web/me.jpg或者http://127.0.0.1:8080/web/me.jpg
但是,该环境中,android和windows是两个不同的系统,故不能用
而只能用本机的IP(局域网中的IP地址):如http://192.168.0.186:8080/web/me.jpg
备注:使用ipconfig命令查看本机IP
查看本机IP的方法:在开始——》搜索程序——》输入cmd——》输入ipconfig命令——》查看本机的IP地址
***********************************************************************************************************
********************************************2012-11-27*****************************************************
十四、Android获取html网页代码
1、通过Connection从网络上获取HTML代码,并显示在TextView控件中
2、步骤:
a、设计界面,为了让TextView可滚动,将其放在一个ScrollView控件中,这样文字就可以滚动了
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:id="@+id/viewer"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</ScrollView>
b、代码:
/**
* 主程序类
* @author HuangYucai
*/
public class HtmlViewerActivity extends Activity {
/** Called when the activity is first created. */
private EditText pathText;
private Button viewBnt;
private TextView txtViewer;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
pathText= (EditText)this.findViewById(R.id.path);
viewBnt=(Button)this.findViewById(R.id.bnt);
txtViewer=(TextView)this.findViewById(R.id.viewer);
viewBnt.setOnClickListener(new BntOnclickListener());
}
public final class BntOnclickListener implements View.OnClickListener{
public void onClick(View v) {
String path=pathText.getText().toString();
String html;
try {//获取字符数据设置到TextView空间
html = PageService.getPageStr(path);
txtViewer.setText(html);
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), "获取网页失败", Toast.LENGTH_SHORT).show();
}
}
}
}
/**
*获取html代码数据的service类
* @author HuangYucai
*/
public class PageService {
public static String getPageStr(String path) throws Exception {
String html="";
URL url=new URL(path);
HttpURLConnection conn=(HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
if(conn.getResponseCode()==200){//请求状态成功时
InputStream inStream= conn.getInputStream();
byte[] data=StreamTool.getBytesByStream(inStream);
html=new String(data,"UTF-8");//网页编码格式为"UTF-8"
}
return html;
}
}
/**
* 流处理的工具类
* @author HuangYucai
*/
public class StreamTool {
public static byte[] getBytesByStream(InputStream inStream) throws Exception {
ByteArrayOutputStream baos=new ByteArrayOutputStream();
byte[] buffer= new byte[1024];
int len=0;
while((len=inStream.read(buffer))!=-1){
baos.write(buffer,0,len);
}
return baos.toByteArray();
}
}
4、注意项
a、在访问本机的url时,一般用http://localhost:8080/web/index.jsp或者http://127.0.0.1:8080/web/index.jsp
但是,该环境中,android和windows是两个不同的系统,故不能用
而只能用本机的IP(局域网中的IP地址):如http://192.168.0.186:8080/web/index.jsp
b、在将字节数组转换为字符串数据时,要指定编码格式,而且要与网页的编码一致,否则出现乱码
***********************************************************************************************************
发表评论
-
设置页面不默认缓存方法
2015-04-21 21:47 690HTTP: <META HTTP-EQUIV ... -
中文乱码解决方案
2013-06-25 00:33 1413中文乱码解决方案 > ... -
android通过POST和GET两种方式发送数据到web应用实战
2012-12-18 21:21 1491一、web应用端 1、servlet package co ... -
android从web应用读取xml和json数据实战
2012-12-13 22:43 1316一、web应用主要代码: 1、domian News.jav ... -
Android自学笔记
2012-12-11 22:41 890=============================== ... -
Android学习笔记2012年(上)
2012-11-27 20:57 875Android学习笔记2012年 一、Android应用的目 ... -
解决网站高并发问题
2012-07-12 00:09 1895在大型网站开发和设计 ...
相关推荐
在深入探讨Android开发之前,我们先来了解一下这个标题——"Android学习笔记",这表明了本文档是作者在阅读《Professional Android 4 Application Development》这本书时所作的笔记,旨在帮助读者理解Android应用...
- **更新记录**:详细记录了每一章节完成的时间,从2012年12月15日开始至2013年3月30日,涵盖了多个章节的编写过程,包括对标准库的不断补充和完善。 - **目录**:本书分为两大部分,第一部分涉及Python语言的基础...
- 2012年1月11日,Go语言版本号从R60升级到了Go 1.0。 - 2012年3月29日,Go 1.0版本正式发布,这是一个重要的里程碑,标志着Go语言从实验阶段走向了成熟稳定。 - 在后续几年中,Go语言经历了多个版本的迭代更新,每...
### Android学习笔记 **作者:tracytheron** **主要内容:** tracytheron撰写的14篇文章记录了他在学习Android开发过程中的心得体会。这些笔记不仅包含了技术细节,还包括了一些个人感悟和建议,对于正在学习的...
- 报名截止时间是2012年5月31日。 - 杂志定价为8元/半月,全年共24期。杂志正常通过平寄方式邮寄,邮费由杂志社承担。 - 订阅活动不适用于邮局订阅等渠道,读者可以选择在杂志社邮购、网上商城或现场订购。 3. ...
### 传智播客2012年C#基础班笔记(第六天)苏坤主讲 #### .NET平台及C#概述 - **.NET Framework**:.NET框架是由微软开发的一个强大的软件开发平台,它支持多种编程语言,包括C#、VB.NET等,并提供了一套完整的...
2012年,Google在最新的Chrome for Android版本中正式支持WebRTC,这标志着WebRTC技术开始走向成熟,并且吸引了越来越多开发者和企业的关注。如今,WebRTC不仅被集成到主流浏览器中,还被广泛应用于各类应用场景,...
这可能是为特定日期(2012年5月17日)更新的表情库。此外,“新建文本文档 (2).txt”可能包含了关于表情包的说明、更新历史或者开发者笔记。 “FaceDemo”这个文件名可能指向一个演示程序或测试工具,用于展示如何...
截至2012年7月,推荐的版本是JDK 7u5。可以从Oracle官网下载:[http://www.oracle.com/technetwork/java/javase/downloads/index.html](http://www.oracle.com/technetwork/java/javase/downloads/index.html) 2. *...
首先,Windows 8是微软在2012年推出的一款全新操作系统,旨在整合桌面与移动设备体验,引入了现代UI(以前称为Metro UI)和触控优化的功能。这一设计目标直接挑战了iOS和Android在移动市场的主导地位。Windows 8的...
2012年,QT又被Digia公司收购。2014年,QT实现了对iOS、Android、WP等各平台的全面支持。 3. QT支持的平台 QT支持多种平台,包括Windows、Unix/X11、Macintosh、Embedded等。其中,Windows平台支持XP、Vista、Win...
本课程包是2012年由杨云教授编著的“互联网软件应用于开发”的教学资料,主要针对成人教育领域。在这个信息化高度发达的时代,互联网软件开发已经成为各行各业不可或缺的一部分,因此,这样的课程对于提升成年人的...
- **替代传统BI方案**:相比于传统的商业智能工具,Tableau Server 提供更直观的操作界面,降低了学习曲线。 - **即时数据分析**:支持对各种数据源的即时分析和混合处理,大幅缩短数据探索时间。 - **自助式分析...
出版,版权日期为2012年。PhoneGap是一种允许开发者使用HTML、CSS和JavaScript等Web技术来构建跨平台移动应用程序的框架。本书从安装配置到高级功能的实现,系统地介绍了PhoneGap的核心概念和技术要点。 #### 二、...
2. **操作系统**:Windows 8在2012年底发布,2013年是其普及初期,因此可能会有大量关于Windows 8新特性的介绍,包括其全新的Metro界面、触控支持和Windows Store。此外,Windows 7仍然是主流,对于它的优化和使用...
Windows 8是微软公司在2012年推出的一款操作系统,它针对企业用户进行了特别优化,尽管在初期遭受了市场的抵触,主要是因为取消了经典的“开始”按钮和引入了与传统桌面操作有所区别的磁贴式界面,但是当企业愿意...