浏览器端javascript调用手机终端本地功能实现02-功能点汇总
上篇博文已经说明,本篇直接进入主题。本篇大致说明总体功能以及代码用途,下篇将功能点逐一详细说明。
功能点包括:
- 拍照相关接口(camera)
功能函数名称 |
作用 |
备注 |
invokeCamera() |
调用摄像头拍照 |
|
requestAlbum() |
调用相册功能 |
|
requestAlbumMulti() |
相册多选 |
|
requestAlbumMultiUpload() |
相册多选完后上传 |
|
2. 录音相关接口(media)
功能函数名称 |
作用 |
备注 |
startRecord() |
录制音频 |
|
stopRecord() |
停止录制 |
|
playRecord() |
播放录制完成的音频 |
|
stopPlay() |
停止播放录制完成的音频 |
|
upload() |
上传音频文件 |
|
3. 二维码、条形码扫码(scan)
功能函数名称 |
作用 |
备注 |
scan() |
扫描条码 |
|
4. 其他接口
功能函数名称 |
作用 |
备注 |
saveLoginInfo () |
保存登陆信息 |
app需要web浏览器网页数据时 |
PS:后续会根据需要增加其他功能
调用摄像拍照,上传语音文件等功能,最终要上传到服务器。所以请先搭建好服务器,这里我是自己搭建了PHP服务器。接收请求参数file,类型为文件,服务器部分您可以自己实现,不在本博文内容范围内。后期为便于大家测试之用,应该会将接口公布在外网。
将分3部分说明,贴出部分代码,后续文章同样遵循此步骤。
1.JS文件部分
- android部分采用系统addJavascriptInterface添加js接口的方式实现
- ios部分采用拦截特定的请求实现
- 核心js函数(之后的js调用都用到此函数)
1 /** 2 *@description Web js communications with mobile terminal local function 3 *@author yanrongxiang 4 *@date 2014-7-17 5 */ 6 function controllerCenter(type,cmd,params){ 7 if(navigator.userAgent.toLowerCase().indexOf('iphone')>0){ 8 document.location="http://QM_APP_WEBVIEW_ENGINE:"+cmd+":"+params; 9 }else if(navigator.userAgent.indexOf('Android')>0){ 10 eval('javascript:QM_APP_WEBVIEW_ENGINE_'+type+'.'+cmd+'("'+params+'")'); 11 }else{ 12 alert("Can't use this feature"); 13 } 14 }
使用javascript调用摄像头及相册部分
1 //Access to the camera function 2 var $camera={ 3 "invokeCamera":function(params){ 4 controllerCenter('camera','invoke_camera',params); 5 }, 6 "requestAlbum":function(params){ 7 controllerCenter('camera','request_albums',params); 8 }, 9 "requestAlbumMulti":function(params){ 10 controllerCenter('camera','request_albums_multi',params); 11 }, 12 "requestAlbumMultiUpload":function(params){ 13 controllerCenter('camera','request_albums_multi_upload',params); 14 } 15 }
使用javascript调用录音,播放部分
1 //Access to the media function 2 var $media={ 3 "startRecord":function(params){ 4 controllerCenter('media','start_record',params); 5 }, 6 "stopRecord":function(params){ 7 controllerCenter('media','stop_record',params); 8 }, 9 "playRecord":function(params){ 10 controllerCenter('media','play_record',params); 11 }, 12 "stopPlay":function(params){ 13 controllerCenter('media','stop_play',params); 14 }, 15 "upload":function(params){ 16 controllerCenter('media','upload_to_server',params); 17 } 18 }
使用javascript调用二维码,条形码扫描部分
1 var $scanbar={ 2 "scan":function(params){ 3 controllerCenter('scan','scan_bar',params); 4 } 5 }
2.android端实现
说明:以下为android应用启动展现的第一个activity,在此activity里面放入Webview控件,请求服务器html页面
1 package com.qimeng.activity; 2 3 import java.io.File; 4 import java.io.FileNotFoundException; 5 import java.io.FileOutputStream; 6 import java.io.IOException; 7 import java.util.ArrayList; 8 import java.util.List; 9 10 import android.annotation.SuppressLint; 11 import android.app.AlertDialog; 12 import android.app.Notification; 13 import android.content.ContentResolver; 14 import android.content.DialogInterface; 15 import android.content.DialogInterface.OnKeyListener; 16 import android.content.res.Resources; 17 import android.content.Intent; 18 import android.graphics.Bitmap; 19 import android.graphics.BitmapFactory; 20 import android.net.Uri; 21 import android.os.Bundle; 22 import android.os.Environment; 23 import android.os.Handler; 24 import android.util.Log; 25 import android.view.KeyEvent; 26 import android.view.View; 27 import android.view.View.OnClickListener; 28 import android.webkit.JsResult; 29 import android.webkit.WebChromeClient; 30 import android.webkit.WebSettings; 31 import android.webkit.WebView; 32 import android.widget.Button; 33 import android.widget.EditText; 34 import android.widget.TextView; 35 import android.widget.Toast; 36 37 import com.baidu.android.pushservice.BasicPushNotificationBuilder; 38 import com.baidu.android.pushservice.CustomPushNotificationBuilder; 39 import com.baidu.android.pushservice.PushConstants; 40 import com.baidu.android.pushservice.PushManager; 41 import com.qimeng.R; 42 import com.qimeng.api.JSInterfaceAPI; 43 import com.qimeng.common.BaseActivity; 44 import com.qimeng.common.IBaseActivity; 45 import com.qimeng.workman.common.imgsupload.util.Bimp; 46 import com.qimeng.workman.common.imgsupload.util.FileUtils; 47 48 /** 49 * 50 */ 51 @SuppressLint("SetJavaScriptEnabled") public class IndexActivity extends BaseActivity implements IBaseActivity { 52 private String[] paramJS; 53 EditText tv_url; 54 public WebView webView; 55 private Handler myHandler; 56 JSInterfaceAPI jsApi = new JSInterfaceAPI(); 57 private static final int REQUEST_CODE_UPLOAD = 300; 58 public static final int REQUEST_CODE_MULTI_UPLOAD = 3001; 59 public static final int REQUEST_CODE_MEDIA_UPLOAD = 3002; 60 private JSInterfaceCamera jsInterfaceCamera; 61 private JSInterfaceMedia jsInterfaceMedia; 62 private JSInterfaceSetting jsInterfaceSetting; 63 private JSInterfaceScanbar jsInterfaceScanbar; 64 public int currentUploadNums=0; 65 @Override 66 protected void onCreate(Bundle savedInstanceState) { 67 super.onCreate(savedInstanceState); 68 setContentView(R.layout.activity_index); 69 myHandler=new Handler(); 70 webView=(WebView)this.findViewById(R.id.webview); 71 webView.getSettings().setJavaScriptEnabled(true); 72 //webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); 73 //webView.getSettings().setAllowFileAccess(true);// 设置允许访问文件数据 74 //webView.getSettings().setSupportZoom(true); 75 //webView.getSettings().setBuiltInZoomControls(true); 76 //webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); 77 //webView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); 78 //webView.getSettings().setDomStorageEnabled(true); 79 //webView.getSettings().setDatabaseEnabled(true); 80 //webView.getSettings().setLoadsImagesAutomatically(true); 81 tv_url=(EditText)findViewById(R.id.tv_url); 82 Button btn=(Button)findViewById(R.id.btn_ok); 83 tv_url.setText("http://10.1.2.123/webview/"); 84 btn.setOnClickListener(new OnClickListener() { 85 @Override 86 public void onClick(View arg0) { 87 webView.loadUrl(tv_url.getText().toString()); 88 } 89 }); 90 91 webView.setWebChromeClient(new WebChromeClient(){ 92 @Override 93 public boolean onJsAlert(WebView view, String url, String message, 94 JsResult result) { 95 AlertDialog.Builder builder = new AlertDialog.Builder(view.getContext()); 96 builder.setTitle("提示").setMessage(message).setPositiveButton("确定", null); 97 // 不需要绑定按键事件 98 // 屏蔽keycode等于84之类的按键 99 builder.setOnKeyListener(new OnKeyListener() { 100 public boolean onKey(DialogInterface dialog, int keyCode,KeyEvent event) { 101 Log.v("onJsAlert", "keyCode==" + keyCode + "event="+ event); 102 return true; 103 } 104 }); 105 // 禁止响应按back键的事件 106 builder.setCancelable(false); 107 AlertDialog dialog = builder.create(); 108 dialog.show(); 109 result.confirm();// 因为没有绑定事件,需要强行confirm,否则页面会变黑显示不了内容。 110 return true; 111 } 112 }); 113 jsInterfaceCamera=new JSInterfaceCamera(this, myHandler); 114 jsInterfaceMedia=new JSInterfaceMedia(this, myHandler); 115 jsInterfaceSetting=new JSInterfaceSetting(this, myHandler); 116 jsInterfaceScanbar=new JSInterfaceScanbar(this, myHandler); 117 //添加js与本地代码通讯接口 118 webView.addJavascriptInterface(jsInterfaceCamera, "QM_APP_WEBVIEW_ENGINE_camera"); 119 webView.addJavascriptInterface(jsInterfaceMedia, "QM_APP_WEBVIEW_ENGINE_media"); 120 webView.addJavascriptInterface(jsInterfaceSetting, "QM_APP_WEBVIEW_ENGINE_setting"); 121 webView.addJavascriptInterface(jsInterfaceScanbar, "QM_APP_WEBVIEW_ENGINE_scan"); 122 //集成百度推送 123 PushManager.startWork(this, PushConstants.LOGIN_TYPE_API_KEY, "SQgonTuwWx3cQc2wPxYimgCQ"); 124 Resources resource = this.getResources(); 125 String pkgName = this.getPackageName(); 126 CustomPushNotificationBuilder cBuilder = new CustomPushNotificationBuilder( 127 getApplicationContext(), resource.getIdentifier( 128 "notification_custom_builder", "layout", pkgName), 129 resource.getIdentifier("notification_icon", "id", pkgName), 130 resource.getIdentifier("notification_title", "id", pkgName), 131 resource.getIdentifier("notification_text", "id", pkgName)); 132 cBuilder.setNotificationFlags(Notification.FLAG_AUTO_CANCEL); 133 cBuilder.setNotificationDefaults(Notification.DEFAULT_SOUND 134 | Notification.DEFAULT_VIBRATE); 135 //cBuilder.setStatusbarIcon(this.getApplicationInfo().icon); 136 cBuilder.setLayoutDrawable(resource.getIdentifier("simple_notification_icon", "drawable", pkgName)); 137 PushManager.setNotificationBuilder(this, 1, cBuilder); 138 } 139 140 public void refresh(final Object... param) { 141 super.refresh(param); 142 int flag = ((Integer) param[0]).intValue();// 获取第一个参数 143 switch (flag) { 144 case 10001: 145 break; 146 case REQUEST_CODE_UPLOAD: 147 webView.post(new Runnable() { 148 @Override 149 public void run() { 150 webView.loadUrl("javascript:"+paramJS[1]+"(\""+(paramJS.length>=2?param[1].toString():"Can't get the callback, confirm your parameters correctly")+"\")"); 151 } 152 }); 153 break; 154 case REQUEST_CODE_MULTI_UPLOAD: 155 currentUploadNums++; 156 webView.post(new Runnable() { 157 @Override 158 public void run() { 159 webView.loadUrl("javascript:"+paramJS[1]+"(\""+(paramJS.length>=2?param[1].toString():"Can't get the callback, confirm your parameters correctly")+"\","+Bimp.drr.size()+","+currentUploadNums+")"); 160 if(currentUploadNums<Bimp.drr.size()){ 161 File f=new File(Bimp.drr.get(currentUploadNums).toString()); 162 jsApi.uploadPhoto((paramJS[0].indexOf("http:")==0?"":"http://")+paramJS[0], f, IndexActivity.this, IndexActivity.REQUEST_CODE_MULTI_UPLOAD); 163 } 164 } 165 }); 166 break; 167 case REQUEST_CODE_MEDIA_UPLOAD: 168 webView.post(new Runnable() { 169 @Override 170 public void run() { 171 jsInterfaceMedia.isRecorded=0; 172 webView.loadUrl("javascript:"+paramJS[1]+"(\""+(paramJS.length>=2?param[1].toString():"Can't get the callback, confirm your parameters correctly")+"\")"); 173 } 174 }); 175 break; 176 } 177 } 178 179 public void initListener() { 180 super.initListener(); 181 } 182 183 public void initView() { 184 super.initView(); 185 } 186 private Bitmap bmp; 187 protected void onActivityResult(int requestCode, int resultCode, final Intent data) { 188 super.onActivityResult(requestCode, resultCode, data); 189 if(requestCode==jsInterfaceScanbar.SELECT_SCANER){ 190 if(resultCode == 1){ 191 Bundle bundle = data.getExtras(); 192 Log.e("##############JFKDJFDKJFKDFJ############", "{\"Result\":\""+bundle.getString("Result")+",\"Format\":\""+bundle.getString("Format")+"\"}"); 193 webView.loadUrl("javascript:"+paramJS[0]+"({\"Result\":\""+bundle.getString("Result")+"\",\"Format\":\""+bundle.getString("Format")+"\"})"); 194 } 195 }else{ 196 if(resultCode == RESULT_OK){ 197 upload_carmare_photo(data); 198 } 199 } 200 } 201 protected void onRestart() { 202 super.onRestart(); 203 if(Bimp.drr.size()>0){ 204 // 如果为相册多选回到主界面时 205 StringBuffer sb=new StringBuffer(); 206 //List<String> list = new ArrayList<String>(); 207 sb.append("["); 208 for (int i = 0; i < Bimp.drr.size(); i++) { 209 //String Str = Bimp.drr.get(i).substring( 210 // Bimp.drr.get(i).lastIndexOf("/") + 1, 211 // Bimp.drr.get(i).lastIndexOf(".")); 212 //list.add(FileUtils.SDPATH+Str+".JPEG"); 213 sb.append("{\"path\":\""+Bimp.drr.get(i).toString()+"\"}"); 214 if(i<Bimp.drr.size()-1){ 215 sb.append(","); 216 } 217 } 218 sb.append("]"); 219 final String sbStr=sb.toString(); 220 //调用网页函数 221 if(paramJS.length>2){ 222 webView.post(new Runnable() { 223 @Override 224 public void run() { 225 webView.loadUrl("javascript:"+paramJS[2]+"("+sbStr+")"); 226 } 227 }); 228 }else{ 229 webView.loadUrl("javascript:"+paramJS[2]+"(\"Can't get the callback, confirm your parameters correctly\")"); 230 } 231 } 232 } 233 public String[] getParamJS() { 234 return paramJS; 235 } 236 237 public void setParamJS(String[] paramJS) { 238 this.paramJS = paramJS; 239 } 240 241 public void upload_carmare_photo(final Intent data){ 242 Thread thread=new Thread(){ 243 @Override 244 public void run() { 245 super.run(); 246 //选择图片 247 Uri uri = data.getData(); 248 ContentResolver cr = IndexActivity.this.getContentResolver(); 249 try { 250 if(bmp != null)//如果不释放的话,不断取图片,将会内存不够 251 bmp.recycle(); 252 bmp = BitmapFactory.decodeStream(cr.openInputStream(uri)); 253 } catch (FileNotFoundException e) { 254 // TODO Auto-generated catch block 255 e.printStackTrace(); 256 } 257 System.out.println("the bmp toString: " + bmp); 258 File fileDir = new File(Environment.getExternalStorageDirectory() + "/Myimage"); 259 if (!fileDir.exists()) { 260 fileDir.mkdirs();// 创建文件夹 261 } 262 File file = new File(Environment.getExternalStorageDirectory() 263 + "/Myimage/", String.valueOf(System.currentTimeMillis()) 264 + ".png"); 265 FileOutputStream fos; 266 try { 267 fos = new FileOutputStream(file); 268 bmp.compress(Bitmap.CompressFormat.JPEG, 50, fos); 269 fos.flush(); 270 fos.close(); 271 } catch (FileNotFoundException e) { 272 // TODO Auto-generated catch block 273 e.printStackTrace(); 274 } catch (IOException e) { 275 // TODO Auto-generated catch block 276 e.printStackTrace(); 277 } 278 if(bmp!=null){ 279 jsApi.uploadPhoto((paramJS[0].indexOf("http:")==0?"":"http://")+paramJS[0], file, IndexActivity.this, REQUEST_CODE_UPLOAD); 280 } 281 } 282 283 }; 284 thread.start(); 285 } 286 }
3.IOS端实现
说明:以下为IOS应用启动展现的第一个ViewController,在此视图控制器里面放入UIWebview控件,请求服务器html页面
1 // 2 // QMViewController.m 3 // QMWebView 4 // 5 // Created by Qimeng Tech on 14-7-15. 6 // Copyright (c) 2014年 Qimeng Tech. All rights reserved. 7 // 8 9 #import "QMViewController.h" 10 #import "QMUtil.h" 11 #import "SecurityUtil.h" 12 #import "JSONKit.h" 13 #import "FileUtil.h" 14 #import "Toast+UIView.h" 15 #import "MLAudioRecorder.h" 16 #import "AmrRecordWriter.h" 17 #import <AVFoundation/AVFoundation.h> 18 #import "MLAudioMeterObserver.h" 19 20 @interface QMViewController () 21 @property (nonatomic, strong) MLAudioRecorder *recorder; 22 @property (nonatomic, strong) AmrRecordWriter *amrWriter; 23 24 @property (nonatomic, strong) AVAudioPlayer *player; 25 26 @property (nonatomic, copy) NSString *filePath; 27 @property (weak, nonatomic) IBOutlet UIButton *recordButton; 28 @property (nonatomic, strong) MLAudioMeterObserver *meterObserver; 29 @property (nonatomic,strong) NSTimer *timerStopRecord; 30 @property (nonatomic,assign) int timerStopNum; 31 @end 32 33 @implementation QMViewController 34 @synthesize currentParams,webView; 35 @synthesize currentUploadPhotoNum,selectMultiUploadPhotoUrls; 36 - (void)viewDidLoad 37 { 38 [super viewDidLoad]; 39 self.title=@"启梦浏览器"; 40 if( ([[[UIDevice currentDevice] systemVersion] doubleValue]>=7.0)) { 41 self.edgesForExtendedLayout = UIRectEdgeNone; 42 self.extendedLayoutIncludesOpaqueBars = NO; 43 self.modalPresentationCapturesStatusBarAppearance = NO; 44 } 45 self.webView=[[UIWebView alloc] initWithFrame:CGRectMake(0, 0, UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT-20-44)]; 46 self.webView.delegate=self; 47 [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://10.1.2.123/webview/"]]]; 48 [self.view addSubview:self.webView]; 49 50 self.selectMultiUploadPhotoUrls=[[NSMutableArray alloc] init]; 51 // Do any additional setup after loading the view, typically from a nib. 52 } 53 #pragma mark -- 54 #pragma mark UIWebViewDelegate 55 /** 56 *截获特殊请求url,完成js与本地交互 57 */ 58 - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { 59 60 NSString *requestString = [[request URL] absoluteString]; 61 NSArray *components = [requestString componentsSeparatedByString:@":"]; 62 NSRange range=[[components objectAtIndex:1] rangeOfString:@"QM_APP_WEBVIEW_ENGINE"]; 63 if ([components count] > 3 && range.location == 2 && range.length == 21) { 64 NSString *cmd=(NSString *)[components objectAtIndex:2]; 65 //上传参数1、请求地址;2、成功回调函数;3、失败回调函数 66 NSArray *params=[[components objectAtIndex:3] componentsSeparatedByString:@","]; 67 //请求相册列表 68 self.currentParams=params; 69 if([cmd isEqualToString:JS_CMD_NAME_ALBUM]){ 70 [QMUtil LocalPhotos:self delegate:self]; 71 //调用摄像头 72 }else if ([cmd isEqualToString:JS_CMD_NAME_CAMERA]){ 73 [QMUtil takeCamera:self delegate:self]; 74 //请求相册列表-多选 75 }else if([cmd isEqualToString:JS_CMD_NAME_request_albums_multi]){ 76 [FileUtil cleaerImgAreaDirectory]; 77 [FileUtil createImgAreaUploadDirectory]; 78 [self.selectMultiUploadPhotoUrls removeAllObjects]; 79 self.currentUploadPhotoNum=0; 80 [QMUtil LocalPhotosSelectMulti:self delegate:self]; 81 }else if([cmd isEqualToString:JS_CMD_NAME_request_albums_multi_upload]){ 82 if (self.selectMultiUploadPhotoUrls.count>0) { 83 [NetWorkUtil uploadFile:[NSString stringWithFormat:@"http://%@",[self.currentParams objectAtIndex:0]] localFilePath:[self.selectMultiUploadPhotoUrls objectAtIndex:0] uploadDelegate:self params:nil code:@"upload_photos_multi"]; 84 }else{ 85 [self.view makeToast:@"没有选择上传图片,无法上传" duration:2.0 position:@"center"]; 86 } 87 //录制音频 88 }else if([cmd isEqualToString:@"start_record"]){ 89 if(self.amrWriter==nil){ 90 [self initRecorder]; 91 } 92 if (self.recorder.isRecording) { 93 //取消录音 94 [self.view makeToast:@"正在录音中,请先停止" duration:2.0 position:@"center"]; 95 }else{ 96 //开始录音 97 [self.recorder startRecording]; 98 self.meterObserver.audioQueue = self.recorder->_audioQueue; 99 //防止用户不停止,录音会一直继续下去 100 self.timerStopNum=0; 101 self.timerStopRecord=[NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(timerFired:) userInfo:nil repeats:NO]; 102 } 103 }else if([cmd isEqualToString:@"stop_record"]){ 104 if(self.amrWriter==nil){ 105 [self initRecorder]; 106 } 107 if (self.recorder.isRecording) { 108 //取消录音 109 [self.recorder stopRecording]; 110 if(self.timerStopRecord!=nil){ 111 [self.timerStopRecord invalidate]; 112 self.timerStopRecord=nil; 113 } 114 }else{ 115 [self.view makeToast:@"还没开始录音" duration:2.0 position:@"center"]; 116 } 117 }else if([cmd isEqualToString:@"play_record"]){ 118 if(self.player==nil){ 119 self.player = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:self.filePath] error:nil]; 120 } 121 NSLog(@"%@",self.filePath); 122 if([self.player isPlaying]){ 123 [self.view makeToast:@"正在播放中,请先停止" duration:2.0 position:@"center"]; 124 }else{ 125 [self.player play]; 126 } 127 }else if([cmd isEqualToString:@"stop_play"]){ 128 if(self.player==nil){ 129 self.player = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:self.filePath] error:nil]; 130 } 131 NSLog(@"%@",self.filePath); 132 if([self.player isPlaying]){ 133 [self.player stop]; 134 } 135 }else if([cmd isEqualToString:@"upload_to_server"]){ 136 if(!self.filePath){ 137 [self.view makeToast:@"请先录制音频" duration:2.0 position:@"center"]; 138 return NO; 139 } 140 [NetWorkUtil uploadFile:[NSString stringWithFormat:@"http://%@",[self.currentParams objectAtIndex:0]] localFilePath:self.filePath uploadDelegate:self params:nil code:@"upload_media"]; 141 }else if([cmd isEqualToString:@"save_login_info"]){ 142 NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults]; 143 if ([self.currentParams count]>=3) { 144 [defaults setObject:[self.currentParams objectAtIndex:0] forKey:@"uid"]; 145 }else{ 146 [self.view makeToast:@"请设置正确的参数" duration:2.0 position:@"center"]; 147 } 148 [defaults synchronize]; 149 //发送推送的userid到服务器 150 //[NetWorkUtil uploadFile:[NSString stringWithFormat:@"http://%@",[self.currentParams objectAtIndex:0]] localFilePath:self.filePath uploadDelegate:self params:nil code:@"upload_media"]; 151 }else if ([cmd isEqualToString:@"scan_bar"]){ 152 if (TARGET_IPHONE_SIMULATOR) { 153 ZBarReaderViewController *controller=[[ZBarReaderViewController alloc] initWithNibName:nil bundle:nil]; 154 [self presentModalViewController:controller animated:YES]; 155 } 156 } 157 return NO; 158 } 159 return YES; 160 } 161 -(void) timerFired:(id)sender{ 162 self.timerStopNum++; 163 if(self.timerStopNum==5){ 164 if (self.recorder&&self.recorder.isRecording){ 165 [self.recorder stopRecording]; 166 NSLog(@"时间到,已自动停止录音"); 167 [self.timerStopRecord invalidate]; 168 self.timerStopRecord=nil; 169 } 170 } 171 } 172 #pragma make QBImagePickerControllerDelegate delegate 173 #pragma make UIImagePickerControllerDelegate 174 //当选择一张图片后进入这里 175 -(void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary *)info 176 { 177 //系统自带的相册单选 178 if ([picker isKindOfClass:[UIImagePickerController class]]) { 179 NSString *type = [info objectForKey:UIImagePickerControllerMediaType]; 180 //当选择的类型是图片 181 if ([type isEqualToString:@"public.image"]){ 182 //关闭相册界面 183 [picker dismissViewControllerAnimated:YES completion:^{}]; 184 //先把图片转成NSData 185 UIImage* image = [info objectForKey:@"UIImagePickerControllerOriginalImage"]; 186 NSData *data; 187 //if (UIImagePNGRepresentation(image) == nil){ 188 data = UIImageJPEGRepresentation(image, 0.5); 189 //} 190 //else{ 191 // data = UIImagePNGRepresentation(image); 192 //} 193 //图片保存的路径 194 //这里将图片放在沙盒的documents文件夹中 195 NSString * DocumentsPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]; 196 //文件管理器 197 NSFileManager *fileManager = [NSFileManager defaultManager]; 198 //把刚刚图片转换的data对象拷贝至沙盒中 并保存为image.png 199 [fileManager createDirectoryAtPath:DocumentsPath withIntermediateDirectories:YES attributes:nil error:nil]; 200 NSString *path=[DocumentsPath stringByAppendingString:@"/image.png"]; 201 [fileManager createFileAtPath:path contents:data attributes:nil]; 202 //得到选择后沙盒中图片的完整路径 203 //NSString *filePath = [[NSString alloc]initWithFormat:@"%@%@",DocumentsPath, @"/image.png"]; 204 205 //创建一个选择后图片的小图标放在下方 206 //类似微薄选择图后的效果 207 UIImageView *smallimage = [[UIImageView alloc] initWithFrame:CGRectMake(50, 120, 40, 40)]; 208 smallimage.image = image; 209 210 //上传图片 211 [NetWorkUtil uploadFile:[NSString stringWithFormat:@"http://%@",[self.currentParams objectAtIndex:0]] localFilePath:path uploadDelegate:self params:nil code:@"upload_photo"]; 212 //操作完后回调网页js 213 //[webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"%@('nihao')",[picker.userParam objectAtIndex:1]]]; 214 ; 215 //加在视图中 216 //[self.view addSubview:smallimage]; 217 } 218 }else{ 219 //自定义的相册多选 220 NSArray *mediaInfoArray = (NSArray *)info; 221 NSLog(@"Selected %d photos and mediaInfoArray==%@", mediaInfoArray.count,mediaInfoArray); 222 NSString *resultJson=@"["; 223 for (int i=0;i<mediaInfoArray.count; i++) { 224 NSDictionary *mediaInfo = [mediaInfoArray objectAtIndex:i]; 225 UIImage *image= [mediaInfo objectForKey:@"UIImagePickerControllerOriginalImage"]; 226 NSString *fileUrl=[NSString stringWithFormat:@"%@/local_%d.jpg",[FileUtil getImgAreaUploadDirecoty],i]; 227 image=[QMUtil makeThumbnailFromImage:image scale:0.5]; 228 [UIImageJPEGRepresentation(image, 0.5) writeToFile:fileUrl atomically:YES]; 229 //image=[UIUtil makeThumbnailFromImage:image scale:0.7]; 230 //[UIImagePNGRepresentation(image) writeToFile:fileUrl atomically:YES]; 231 resultJson=[resultJson stringByAppendingString:[NSString stringWithFormat:@"{\"path\":\"%@\"}",fileUrl]]; 232 [self.selectMultiUploadPhotoUrls addObject:fileUrl]; 233 if (i<mediaInfoArray.count-1) { 234 resultJson=[resultJson stringByAppendingString:@","]; 235 } 236 } 237 resultJson=[resultJson stringByAppendingString:@"]"]; 238 [self.webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"%@(%@)",[self.currentParams objectAtIndex:2],resultJson]]; 239 [self dismissViewControllerAnimated:YES completion:NULL]; 240 } 241 242 } 243 - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker 244 { 245 NSLog(@"您取消了选择图片"); 246 [picker dismissViewControllerAnimated:YES completion:^{}]; 247 [self.webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"%@('')",[self.currentParams objectAtIndex:2]]]; 248 } 249 - (void)didReceiveMemoryWarning 250 { 251 [super didReceiveMemoryWarning]; 252 // Dispose of any resources that can be recreated. 253 } 254 -(void) uploadDelegate:(NSString *)response code:(NSString *)code error:(NSError *)error{ 255 if ([response rangeOfString:@"http://"].length==7) { 256 if ([@"upload_photo" isEqualToString:code]) { 257 [self.webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"%@('%@')",[self.currentParams objectAtIndex:1],response]]; 258 }else if([@"upload_photos_multi" isEqualToString:code]) { 259 self.currentUploadPhotoNum++; 260 [self.webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"%@('%@',%d,%d)",[self.currentParams objectAtIndex:1],response,self.selectMultiUploadPhotoUrls.count,self.currentUploadPhotoNum]]; 261 if (self.currentUploadPhotoNum<self.selectMultiUploadPhotoUrls.count) { 262 //继续上传 263 [NetWorkUtil uploadFile:[NSString stringWithFormat:@"http://%@",[self.currentParams objectAtIndex:0]] localFilePath:[self.selectMultiUploadPhotoUrls objectAtIndex:self.currentUploadPhotoNum] uploadDelegate:self params:nil code:@"upload_photos_multi"]; 264 } 265 }else if ([@"upload_media" isEqualToString:code]) { 266 [self.webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"%@('%@')",[self.currentParams objectAtIndex:1],response]]; 267 } 268 269 }else{ 270 [self.webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"%@('%@')",[self.currentParams objectAtIndex:2],response]]; 271 } 272 } 273 274 -(void) initRecorder{ 275 NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; 276 AmrRecordWriter *amrWriter = [[AmrRecordWriter alloc]init]; 277 amrWriter.filePath = [path stringByAppendingPathComponent:@"record.amr"]; 278 amrWriter.maxSecondCount = 60; 279 amrWriter.maxFileSize = 1024*256; 280 amrWriter.cafFilePath = [path stringByAppendingPathComponent:@"recordAmr.caf"]; 281 self.amrWriter = amrWriter; 282 283 284 MLAudioMeterObserver *meterObserver = [[MLAudioMeterObserver alloc]init]; 285 meterObserver.actionBlock = ^(NSArray *levelMeterStates,MLAudioMeterObserver *meterObserver){ 286 NSLog(@"volume:%f",[MLAudioMeterObserver volumeForLevelMeterStates:levelMeterStates]); 287 }; 288 meterObserver.errorBlock = ^(NSError *error,MLAudioMeterObserver *meterObserver){ 289 [[[UIAlertView alloc]initWithTitle:@"错误" message:error.userInfo[NSLocalizedDescriptionKey] delegate:nil cancelButtonTitle:nil otherButtonTitles:@"知道了", nil]show]; 290 }; 291 self.meterObserver = meterObserver; 292 MLAudioRecorder *recorder = [[MLAudioRecorder alloc]init]; 293 __weak __typeof(self)weakSelf = self; 294 recorder.receiveStoppedBlock = ^{ 295 [weakSelf.recordButton setTitle:@"Record" forState:UIControlStateNormal]; 296 weakSelf.meterObserver.audioQueue = nil; 297 }; 298 recorder.receiveErrorBlock = ^(NSError *error){ 299 [weakSelf.recordButton setTitle:@"Record" forState:UIControlStateNormal]; 300 weakSelf.meterObserver.audioQueue = nil; 301 302 [[[UIAlertView alloc]initWithTitle:@"错误" message:error.userInfo[NSLocalizedDescriptionKey] delegate:nil cancelButtonTitle:nil otherButtonTitles:@"知道了", nil]show]; 303 }; 304 recorder.bufferDurationSeconds = 0.04; 305 recorder.fileWriterDelegate = amrWriter; 306 self.filePath = amrWriter.cafFilePath; //因为能直接播放是的caf文件,所以给予caf文件地址 307 self.recorder = recorder; 308 } 309 @end 310 311 @interface UIWebView (JavaScriptAlert) 312 313 - (void)webView:(UIWebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(CGRect *)frame; 314 315 @end 316 317 @implementation UIWebView (JavaScriptAlert) 318 319 - (void)webView:(UIWebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(CGRect *)frame { 320 321 322 UIAlertView* customAlert = [[UIAlertView alloc] initWithTitle:@"提示信息" message:message delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil]; 323 324 [customAlert show]; 325 326 } 327 @end