摘要: 今天配置php 的时候,发现没配起mysql ,wordpress提示我需要 mysql 的module 之后上google搜索,大多数都是说php.ini 没加载起 之后看phpinfo() 里...阅读全文
posted @ 2012-01-26 01:31 Atpking 阅读(105) 评论(2) 编辑

在上一篇“设定定期执行”之后,我们就需要处理将图片上传到指定服务器上了。

我选择的方式是将图片以post的形式传送到服务器上,这个和浏览器中提交图片是一个道理。

 

我们的步骤是

========================

1、启动相机,照相。

2、获得相机的照片文件

3、将照片文件post 提交到服务器端

========================

我们知道android 中的程序是可以通过intent来共享的,我们知道相机照相的公开intent,只需要向其访问就ok了

当然,要调用相机,首先得在manifest 中给相机的调用权限(ps:模拟器现在也可以使用相机功能了,老版本不能用,升级下android development tools 即可,模拟器调用相机好像不需要权限)

    <uses-permission android:name="android.permission.CAMERA" />

 

image

 

由于我们要获得相机的照片文件,所以需要给相机制定我们存储的路径,

我们可以参看google 官方的Taking photos simply 

 

我在这里做了一个dispatchTalking方法来处理这个事情

 

    private void dispatchTakePictureIntent(int actionCode) throws IOException {
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
 
        File f = createImageFile();//生成文件路径
        takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
        startActivityForResult(takePictureIntent, actionCode);
    }

辅助代码如下所示,其中mCurrentPhotoPath为中间变量

    private File createImageFile() throws IOException {
        // Create an image file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
                .format(new Date());
        String imageFileName = JPEG_FILE_PREFIX + timeStamp + "_";
        File image = File.createTempFile(imageFileName, JPEG_FILE_SUFFIX,
                getAlbumDir());
        mCurrentPhotoPath = image.getAbsolutePath();
        return image;
    }

 

    private File getAlbumDir() {
        File storageDir = null;
 
        // 检测sd卡是否可以写入
        if (Environment.MEDIA_MOUNTED.equals(Environment
                .getExternalStorageState())) {
 
            storageDir = mAlbumStorageDirFactory
                    .getAlbumStorageDir(getAlbumName());
 
            if (storageDir != null) {
                if (!storageDir.mkdirs()) {
                    if (!storageDir.exists()) {
                        Log.d(getString(R.string.app_name),
                                "failed to create directory");
                        return null;
                    }
                }
            }
 
        } else {
            Log.v(getString(R.string.app_name),
                    "External storage is not mounted READ/WRITE.");
        }
 
        return storageDir;
    }
 
    private String getAlbumName() {
        return "InspectorAlbum";
    }

 

ok,准备工作完毕,我们调用的时候只需要调用dispatchTakePictureIntent即可,我这里是绑定在optionsMenu里的

case R.id.TakePhoto:
            try {
                dispatchTakePictureIntent(CAMERA_INTENT_SIGN);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                Toast.makeText(getApplicationContext(), "存储照片失败",
                        Toast.LENGTH_SHORT).show();
            }

 

之后接收图片很简单,只需要指定onActivityResult中处理就ok了

 

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
 
        Log.v(getString(R.string.app_name), "resultCode=" + resultCode
                + ",requestCode=" + requestCode);
 
        if (resultCode == Activity.RESULT_OK
                && requestCode == CAMERA_INTENT_SIGN) {
 
            Log.v(getString(R.string.app_name), "存储的相片地址为" + mCurrentPhotoPath);
            
            
            //启动服务,上传图片的干活
            Intent intent = new Intent(getApplicationContext(),
                    UploadImgService.class);
            intent.putExtra("storageURI", mCurrentPhotoPath);
            startService(intent);
 
        }
    }

 

之后就是这个UploadImgService 服务了,我写的这个服务主要的实现目的从名字就可以看的出来:图片的上传

以下是我自己做的service的笔记

---------------------------------------------------------------------------------------

android服务有两种

分为本地service 和 remote service,本地service只调用自己的application 而remote service 可以走其他的application

remote service 使用Android interface definition language (AIDL) 描述自己

什么时候用local service 什么时候用remote service

     当一个service 严格的只被同一个程序的模块调用的时候,客户端应该使用Context.startService() 启动一个service,这个service就是local service,因为他的作用是,为这个application做一个后台的任务。

     如果说service支持onBind()方法,则他是remote service,他可以被Context.bindService()这个线程间通信请求调用。

一般情况下,我们不把一个程序既做成local  又做成remote service     

Local Services

     开始  Context.startService()

     结束  Context.stopService 或 Service 自身调用stopSelf();

当Context.startService() 被调用但是Service还没有被创建的时候,系统会自动初始化,并且调用service的onStartCommand()方法。

如果说调用Context.startService 的时候Service已经开始了,他会重新执行onStartCommand 但没有重新实例化一个服务

     如果说想只做一个Thread 在Service 中,可以考虑将其放入OnCreate 中   保证其只执行一次,但OnCreate 中是无法调用到传来的Intent 的信息的,如果想用Intent 的话,就只有在onStartCommand 用。

AIDL Services

     建立一个Remote Service 的步骤

          1、写一个向client定义的接口的aidl文件,aidl 文件使用java 语法,以aidl 后缀结尾。使用和Android Project同样的命名空间

          2、在Eclipse 的src 下建立此文件,Android Eclipse 插件会调用AIDL 编译器去省城一个java interface

          3、实现一个Service 并且 通过onBind() 返回interface

          4、在manifest文件中加入服务配置

------------------------------------------------------------------------------------------

 

我们在这里使用的是 local service,去发起一个post 提交。

值得注意的是,由于service 仍然是在主线程进行的,所以说,受到5秒规则(程序busy时间超过5s会提示用户是否结束该程序),又由于post一张照片的时间很有可能是大于5s的,所以我们需要在这个服务上再开启一个子线程来处理post提交。

android本身的httpClient 支持post提交,但是对复杂form模型的支持不是很好,这个时候我们需要使用apache的组件httpcomponent来实现,下载地址在这里 下载解压后,我们需要在项目属性的java buildpath 的library添加 httpclient和httpmime  ,他们放在下载文件的lib文件夹里。

image

ok

一步一步来,最先解决如何post一张图片的问题:

我们首先从intent中得到file的地址,之后将其添加到post 提交

 

                List<NameValuePair> params = new ArrayList<NameValuePair>();
 
                params.add(new BasicNameValuePair("image",
                        intent.getStringExtra("storageURI")));
                
                String ServerAddress = settings.getString(
                        "serverip_preference", "http://10.0.2.2:8888/upload");
 
                ImgPostHelper.post(ServerAddress, params);

这里使用了一个自己写的ImgPostHelper 帮助类,代码如下

package info.atpking.cityInspectorsHelper;
 
import java.io.File;
import java.io.IOException;
import java.util.List;
 
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
 
public class ImgPostHelper {
    public static void post(String url, List<NameValuePair> nameValuePairs) {
        HttpClient httpClient = new DefaultHttpClient();
        HttpContext localContext = new BasicHttpContext();
        HttpPost httpPost = new HttpPost(url);
 
        try {
            MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
 
            for(int index=0; index < nameValuePairs.size(); index++) {
                if(nameValuePairs.get(index).getName().equalsIgnoreCase("image")) {
                    // If the key equals to "image", we use FileBody to transfer the data
                    entity.addPart(nameValuePairs.get(index).getName(), new FileBody(new File (nameValuePairs.get(index).getValue())));
                } else {
                    // Normal string data
                    entity.addPart(nameValuePairs.get(index).getName(), new StringBody(nameValuePairs.get(index).getValue()));
                }
            }
 
            httpPost.setEntity(entity);
 
            httpClient.execute(httpPost, localContext);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 

这里相当于我们post提交了一个图片,他的key name 为 image  

之后我们要实现使用一个线程来处理这个上传

我们在服务的OnStart 中填入一个线程

    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        Log.v(TAGLOG, "我被启动了");
 
        Thread thr = new Thread(null, mTask, "AlarmService_Service");
        thr.start();
        this.intent = intent;
    }
之后我们要实现这个mTask   

    Runnable mTask = new Runnable() {
        public void run() {
            // 干活的家伙
            if (intent.getExtras().containsKey("storageURI")) {

                Log.v(getString(R.string.app_name), "在这里上传");
                List<NameValuePair> params = new ArrayList<NameValuePair>();

                params.add(new BasicNameValuePair("image",
                        intent.getStringExtra("storageURI")));
                
                String ServerAddress = settings.getString(
                        "serverip_preference", "http://10.0.2.2:8888/upload");

                ImgPostHelper.post(ServerAddress, params);
                
            }
            UploadImgService.this.stopSelf();
        }


    };
 
 
注意一下,这里的10.0.2.2 是你虚拟机访问你的机器的地址,我在机器上搭建了一个node.js 的接受图片post的小网站。
 
 
 
至此,手机端到这里就完全结束了,下一讲说怎样用node.js 搭建接收端(当然你可以用.net 做一个接收post的页面,什么技术都可以)
posted @ 2012-01-07 21:43 Atpking 阅读(213) 评论(4) 编辑

上一篇博客中我们介绍了怎样让程序一开机就运行

那么,根据我们上次的思路“开机运行一个定时器,定时执行某项服务”,来实现定期执行上传任务

我们需要的是AlarmManager

 

alarmmanager的作用类似于定时器,它可以让android在未来某一时刻运行某个程序,他的好处在于哪怕启动他的activity现在是处于inactive 状态,它仍然会精准的执行,除非你重启设备。

alarmManager 可以支持很多中触发形式,有单次,有循环,有自定义循环三种模式(想想我们闹铃的三种模式),我们可以在API上看到这些信息


set(int type, long triggerAtTime, PendingIntent operation)

Schedule an alarm.
setInexactRepeating(int type, long triggerAtTime, long interval, PendingIntent operation)

Schedule a repeating alarm that has inexact trigger time requirements; for example, an alarm that repeats every hour, but not necessarily at the top of every hour.
setRepeating(int type, long triggerAtTime, long interval, PendingIntent operation)

Schedule a repeating alarm.

 

我们这里使用的是循环    也就是setRepeating

说下这个参数

首先type 是代表计时器的几种不同的计时方式,他们包含ELAPSED_REALTIME、ELAPSED_REALTIME_WAKEUP、RTC、以及RTC_WAKEUP

Elapse 系列是从开机开始算起,包括机器休眠时间   而rtc ,指的是当前时间,之后加没加wakeup 的参数修饰的意思是   到达时间后是否在到达时间后唤醒设备处理(有wakeup),还是等待用户wakeup机器后运行(无walkup)

 

后面的两个triggerAtTime和interval 代表的是起始时间和步长,最后一个是 operation  你需要启动的intent  在这里注意一下,此处的pendingintent 是预备使用的intent

ok,放代码

 

        PendingIntent mAlarmSender = PendingIntent.getService(context, 0, new Intent(
                context, UploadImgService.class), 0);

        long firstTime = SystemClock.elapsedRealtime();
        AlarmManager am = (AlarmManager) context
                .getSystemService(context.ALARM_SERVICE);
        am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstTime,
                10 * 6000, mAlarmSender);

 

注意一下,这个intent 就是我们要运行的服务,

这个含义就是每隔1min运行一次uploadImgService 的这个服务

 

下次我们着重讲uploadImgService 的实现

posted @ 2012-01-05 01:07 Atpking 阅读(45) 评论(0) 编辑

有个小计划练手,就是做一个拍照,之后自动上传到某个服务器上的小demo

思路是这样的,

拍照的时候加一个标志位表示这个照片要同步到网络上且还未上传。

之后系统定期检查是否有上传任务,若有,则执行上传,若没有,则等待至下一次检测点

 

ok,转化为程序思路,具体如下,

为实现自启动,需要捕获我们的设备运行信息,可以使用BroadcastReceiver这个东西

但是我们启动的是alarmManager 

为什么不直接用上传的Service,之后在Service 内部实现一个循环等待的功能?

因为android机制当中,里面的wait 是指你在active 的时候的时间,如果程序本身是inactive或者被pause了的话,等待的时间就会不准。同时,如果一直监听,则service是不会被回收的,这点很不爽。

 

下面就是这个demo的第一步,捕获系统开机,自动运行程序

 

android认为这个事情比较重要,所以要在mainfest 中授权,

授权方式如下

在manifest 根节点下直接添加权限节点

 

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

 

image

 

在有了权限之后,我们还要写一个receiver指定谁接受这个东西

照例,我们需要像activity一样的在mainfest 里指定他  

同时这里因为要捕获系统的启动,所以说需要在intent-filter设置一下  详情如下所示

 

image

 

之后OnBootReceiver 的代码也很简单,

package info.atpking.cityHelper;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class OnBootReceiver extends BroadcastReceiver {
    private static final String LOGTAG = "ATPKINGLOG";
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.v(LOGTAG,"我已随系统启动了哇亲");
        // 在这里接下来我们要开启AlarmManager 了
    }

}

 

之后就可以在虚拟机上跑了。

注意,虚拟机需要首先加载一次这个程序之后才能随系统开机运行

 

直接点运行,出来新建项目时默认的activity后,这个时候系统已经将其receiver 注册了

关掉虚拟机,之后再启动虚拟机,我们就可以在LogCat 上看到我们的开机运行了。

 

 

image

 

下一篇,介绍AlarmManager 的用法

posted @ 2011-12-26 12:15 Atpking 阅读(189) 评论(0) 编辑

不错的入门教程在这里

http://www.ibm.com/developerworks/cn/opensource/os-nodejs/

 

 

现在的node.js(v0.6.5)已经脱离了cygwin了,所以不用在去下载了

安装好msi 之后node 会装在系统盘符的Programs Files 里,同时自动在系统的环境变量里填入了这个值

 

之后我们就可以在cmd里使用node 了

比如最基础的  可以查看node 的版本    node --version   注意,是两个横线,效果如下所示

image

 

我们编写了一个最简单的脚本程序,如下所示

var http = require('http');

http.createServer(function (request,response){
    response.writeHead(200,{'Content-Type':"text/plain"});
    response.end('Hello World\n');
}).listen(8124);

console.log("Server running at http://127.0.0.1:8124/");

 

我将其命名为example.js   存储在D:\CMDFiles 文件夹中 

 

运行这个js 十分简单,如下图所示

image

之后我们可以在浏览器中查看到效果

image

之后信息如下所示

 

image

image

posted @ 2011-12-13 15:10 Atpking 阅读(9) 评论(0) 编辑
摘要: 今日使用Eclipse 的时候,出现了这个问题 layout 文件无法使用intelligence 功能 后来发现eclipse 打开的时候,将其理解为一个“纯粹的”xml文件,平时还有一个视图tab都没有出来 解决方案十分简单,右键点击这个xml,选择 open with …. 之后选择对应的android XXX editor 即可阅读全文
posted @ 2011-12-08 10:08 Atpking 阅读(13) 评论(0) 编辑
摘要: 1、在一对多关系中,我们需要指定一个外键,同时我们使用virtual 这个标识标识另外一个对象的引用 比如说以下模型 public class Phone{ public int Id{get;set;} public int PhoneBrandId{get;set;} public virtual PhoneBrand PhoneBrand{get;set;}}public class Pho...阅读全文
posted @ 2011-05-19 16:09 Atpking 阅读(64) 评论(0) 编辑
摘要: warning:此修改有风险,技术不太好的朋友就别试了 众所周知chrome 的临时文件是存在C盘的 若要将其更改,则可以简单的在启动项后面加入--user-data-dir= “路径” 的方法 但是这种对于其他应用程序调用chrome是无效的 针对这种情况,我们需要更改注册表的 分别在这几个位置加入参数 HKEY_CLASSES_ROOT\http\shell\open\command HKEY...阅读全文
posted @ 2011-03-12 15:25 Atpking 阅读(695) 评论(0) 编辑
摘要: 今天偶然换sql server 2008 登录,平时都用的是windows 账户直接连接登录,就没注意   链接后出现  A connection was successfully established with the server, but then an error occurred during the login process. (provider: Shared memory ...阅读全文
posted @ 2011-01-13 10:53 Atpking 阅读(115) 评论(0) 编辑
摘要: 其实很早的时候就想琢磨下Discuz!NT的一些东西,今天着重吧Discuz 的有关于配置的信息研究了下,拿出来与大家共同分享下 Discuz!NT在web.config自定义了httpModule 模块去实现了IHttpModule 一行一行的讲解:OnlineUsers.ResetOnLineList首先将用户信息清零context.BeginRequest += new EventHandler(ReUrl_BeginRequest) 这行代码指定地址请求处理的方法(ReUrl_BeginRequest这个方法是处理URL 地址的)if(eventTimer == null && Sch阅读全文
posted @ 2011-01-12 00:48 Atpking 阅读(146) 评论(0) 编辑