精华内容
下载资源
问答
  • 教授App Inventor课程

    2017-11-21 11:46:00
    原文链接:http://www.appinventor.org/TeachingAI 本页讨论Wolber教授的USF课程...课程的大部分课程内容都可以“AI course-in-a-box”里找到。 构建——概念化——定制——创建 课程使用“构建——概...

    原文链接:http://www.appinventor.org/TeachingAI

    本页讨论Wolber教授的USF课程"Computing, Mobile Apps, and the Web"中使用的方法,这是一门针对大多数商科和人文学科学生的核心课程。课程的大部分课程内容都可以在“AI course-in-a-box”里找到。

    构建——概念化——定制——创建

     

    课程使用“构建——概念化——自定义——创建”模式。每个模块都遵循“先做”的结构,在激励学生学习方面效果显著。

    构建

    介绍一个主题,但保持简短。在几分钟内,让学生建立一个有趣的应用程序,使用“step-by-step”的教程。

    概念化

    学生完成教程后,将其分成小组讨论有关应用程序的概念性问题,然后进行班级讨论。

    定制

    讨论会之后,分配定制任务,让学生在刚刚构建的应用程序中添加有趣的功能。

    创建

    在经历“构建——概念化——自定义”过程的两三次迭代之后,让学生根据个人兴趣自由选择创建一个应用程序。

     

    创意课堂

    小组讨论和纸上编程

    该模式的关键部分涉及将学生分成小组讨论概念和纸上编程。当学生使用App Inventor在计算机上编写代码时,他们有时会过于机械地跟随教程或样例,或者从同伴得到过多的帮助。通过纸上编程,他们将被引导着放慢速度,思考他们的编程活动和背后的概念。

    我发现,当他们1)刚刚尝试过解决问题,2)已经在与他们的同伴或团队交谈时,学生们更容易参加更大规模的课堂讨论。即使是几分钟的小组(讨论)解决问题的方法,也会加快课堂讨论速度,并让每个人都参与其中。

    我通常鼓励接近同一水平的学生一起工作。把顶尖的学生与正在挣扎的学生配对可以工作,但根据我的经验,这通常不行。

    追踪代码

    除了概念和编码问题,我还让学生跟踪代码。我让他们为相关的属性和变量绘制“内存单元”,然后显示单元中的数据如何在每行(程序)之后改变。在课程或办公时间内的其中一次课程中,“灯泡”开启时,我从不感到惊讶。

    基于代表作品集的学习

    App Inventor的一个优点是初学者可以构建有用而且有趣的应用程序。您可以充分利用这一点,并通过让学生创建他们的代表作品集——显示他们在课堂上创建的应用程序的网站来显著提高学习动力。我强烈鼓励学生向他们的朋友和家人展示他们的应用程序,并将他们的代表作品集看作可以向未来雇主展示的东西。我还鼓励学生在他们的创意项目中设计和构建真正被某个人使用的应用程序,而不仅仅是一个样本(这说起来容易做起来难!)

    整个学期我都在开展应用竞赛,并定期向学生们展示他们的应用。在秋季学期,学生将在USF 计算机科学部门的“CS夜”上演示他们的最终项目,学生,教师,校友以及来自其他大学和更广范围社区的学生。非常有意思的是,初学者,其中大部分不是CS专业的学生,都能够构建有趣的应用程序,与高年级和硕士课程的学生一起演示!毋庸置疑,这些离开了的校友,和高年级的学生们会嫉妒:“我们开始的时候为什么不去做这么酷的东西呢?

    以学生为中心的课程网站

    我的课程网站显示学生的照片。当你点击一张图片时,它会把你带到学生的作品集中,在那里你可以看到他们建立的应用程序。学生将他们的创意项目发布到他们的Google网站上。课程网站和学生网站均使用Google协作平台建立,方便。我还没有做好模板,以及要求学生美化他们的应用程序页面,所以网站看起来不太好。提供这样的模板和一个过程/工具来构建这个模型对于学生和促进班级与学生的工作都是很好的。

    App Inventor Gallery作为学习工作室

    Gallery.appinventor.mit.edu上 有一个App Inventor Gallery 。图库提供了一种方法,让学生与更广泛的社区分享他们的应用程序,并从他人的应用程序中学习。学生们在那里发布他们的应用程序,并下载其他人的应用程序进行混合。把这个图库想象成一个开源的在线学习工作室。

    目前,我们正在与麻省理工学院合作,将一个图库整合到麻省理工学院的App Inventor中,这个活动将使图库成为App Inventor体验的一个组成部分。图库整合预计将于2014年7月底部署。同时,我强烈建议您使用当前的图库。

    测验和代码营

    学期的每周我都会给学生布置一个20分钟的测验。学生可以参加代码营,获得每次测验中失去的1/2的分数。代码营本质上是在办公时间,学生自己在白板上编程,其他学生观看/评论。我将他们在测验中做错的或类似问题分配给他们,如果他们看起来准备好的话,就把更难些的题目分配给他们。因为白板编程迫使学生思考一个问题,并真正理解他们编写的代码,所以它的效果很好。

    由于(App Inventor)编程的“自建”本质,我已经演变为在中期进行频繁的测验。就像数学一样,如果你落后了就很难赶上,特别是那些主要来自商业和人文学校的初学者。频繁的测验和代码营实际上有助于让学生早些开始办公时间,而不是在第一个学期中期后进入学期。

    转载于:https://www.cnblogs.com/wanping/p/7872461.html

    展开全文
  • 抓取得到App音频数据

    万次阅读 2018-06-10 21:41:38
    以前都是网页上抓取数据,很少手机App中抓取数据,那如何抓取手机App中的数据呢?一般我们都是使用抓包工具来抓取数据.常用的抓包工具有Fiddles与Charles,以及其它今天我这里主要说说Charles使用,相比于...

    以前都是在网页上抓取数据,很少在手机App中抓取数据,那如何在抓取手机App中的数据呢?一般我们都是使用抓包工具来抓取数据.


    常用的抓包工具有FiddlesCharles,以及其它今天我这里主要说说Charles使用,相比于FiddlesCharles功能更强大,而且更容易使用. 所以一般抓包我推荐使用Charles


    下载与安装Charles


    下载并安装Charles 再去破解Charles,这里附上文章教程,我就不多说啥了
    https://www.cnblogs.com/rrl92/p/7928770.html


    注意事项:

    如果获取到的数据是乱码,你要设置一下连接SSL证书 在Charles中 菜单栏==>proxy==>SSL Proxying Settings ==>添加443,如上图所示.  然后当你在真正抓取数据的时候,记得把这个关掉,以免取不到数据




    使用Charles


    这里我直接放两张图让大家使用看看就明白了



    我们一起来分析项目.


    • 打开Charles 然后打开手机,得到App,进入逻辑思维栏目. 多次刷新App, 在Charles中 Structure中有变黄的一项就是我们当前的请求,

    • 查看右边的Overview栏目,这里我们很容易发现我们的请求路径,状态,以及请求方式

    • 点击Contents栏目,上面是Requests区域,下面是Response区域. 可以看到上面的Headers 这里就是我们实际写代码时候要用到的Headers,** 注意构造Heaers时,不要出现了空格,我刚刚就犯了这个错误**

    • 再看Form栏目,这里是我们构造Post请求需要的一些参数,我们在请求的时候,注意这里面的数据变化,来找出数据请求的规律.

    • 这里我找到的数据请求规律就是通过改变时间戳来获取数据.

    • 我打算把获取的数据存入到execl中,并下载相关的音频.

    • 我们就开始来写代码. 定义一个dedao类, 定义了三个方法 request_data()parse_data() download_mp3() 代码结构如下: 这里我强调一下,一定要先有大致的思路再去写代码,我这里定义了三个方法,我心中已经知道具体流程了.

    • 另外要注意一下,我能之前说了得到是通过时间戳来去请求下一页数据,那什么时候把数据请求完了呢,以及如何去请求下一页数据, 如果时间戳与我当前存的时间戳不一致,说明还有下一页数据,否则就是数据请求完了,具体代码如下:

        # 这里有点递归的意味
     max_id = datas[-1]['publish_time_stamp']
           if self.max_id != max_id:
               self.max_id = max_id
               self.request_data()
           else:
               print('数据抓取完毕!')

    完整代码:

    import requests

    import time
    import json
    from dedao.ExeclUtils import ExeclUtils
    import os


    class dedao(object):

       def __init__(self):
           # self.rows_title = [u'招聘标题', u'公司名称', u'公司地址', u'待遇', u'发布日期', u'招聘链接', u'招聘要求描述']
           # sheet_name = u'51job_Python招聘'
           self.rows_title = [u'来源目录', u'标题', u'图片', u'分享标题', u'mp3地址', u'音频时长', u'文件大小']
           sheet_name = u'逻辑思维音频'

           return_execl = ExeclUtils.create_execl(sheet_name, self.rows_title)
           self.execl_f = return_execl[0]
           self.sheet_table = return_execl[1]
           self.audio_info = []  # 存放每一条数据中的各元素,
           self.count = 0  # 数据插入从1开始的
           self.base_url = 'https://entree.igetget.com/acropolis/v1/audio/listall'
           self.max_id = 0
           self.headers = {
               'Host': 'entree.igetget.com',
               'X-OS': 'iOS',
               'X-NET': 'wifi',
               'Accept': '*/*',
               'X-Nonce': '779b79d1d51d43fa',
               'Accept-Encoding': 'br, gzip, deflate',
               #     'Content-Length': '    67',
               'X-TARGET': 'main',
               'User-Agent': '%E5%BE%97%E5%88%B0/4.0.13 CFNetwork/901.1 Darwin/17.6.0',
               'X-CHIL': 'appstore',
               'Cookie    ': 'acw_tc=AQAAAC0YfiuHegUAxkvoZRLraUMQyRfH; aliyungf_tc=AQAAAKwCD1dINAUAxkvoZTppW+jezS/9',
               'X-UID': '34556154',
               'X-AV    ': '4.0.0',
               'X-SEID    ': '',
               'X-SCR    ': '1242*2208',
               'X-DT': 'phone',
               'X-S': '91a46b7a31ffc7a2',
               'X-Sign': 'ZTBiZjQyNTI1OTU2MTgwZjYwMWRhMjc5ZjhmMGRlNGI=',
               'Accept-Language': 'zh-cn',
               'X-D': 'ca3c83fca6e84a2d869f95829964ebb8',
               'X-THUMB': 'l',
               'X-T': 'json',
               'X-Timestamp': '1528195376',
               'X-TS': '1528195376',
               'X-U': '34556154',
               'X-App-Key': 'ios-4.0.0',
               'X-OV': '11.4',
               'Connection': 'keep-alive',
               'X-ADV': '1',
               'Content-Type': 'application/x-www-form-urlencoded',
               'X-V': '2',
               'X-IS_JAILBREAK    ': 'NO',
               'X-DV': 'iPhone10,2',
           }

       def request_data(self):
           try:
               data = {
                   'max_id': self.max_id,
                   'since_id': 0,
                   'column_id': 2,
                   'count': 20,
                   'order': 1,
                   'section': 0
               }
               response = requests.post(self.base_url, headers=self.headers, data=data)
               if 200 == response.status_code:
                   self.parse_data(response)
           except Exception as e:
               print(e)
               time.sleep(2)
               pass

       def parse_data(self, response):
           dict_json = json.loads(response.text)
           datas = dict_json['c']['list']  # 这里取得数据列表
           #  print(datas)
           for data in datas:
               source_name = data['audio_detail']['source_name']
               title = data['audio_detail']['title']
               icon = data['audio_detail']['icon']
               share_title = data['audio_detail']['share_title']
               mp3_url = data['audio_detail']['mp3_play_url']
               duction = str(data['audio_detail']['duration']) + '秒'
               size = data['audio_detail']['size'] / (1000 * 1000)
               size = '%.2fM' % size

               self.download_mp3(mp3_url)

               self.audio_info.append(source_name)
               self.audio_info.append(title)
               self.audio_info.append(icon)
               self.audio_info.append(share_title)
               self.audio_info.append(mp3_url)
               self.audio_info.append(duction)
               self.audio_info.append(size)

               self.count = self.count + 1
               ExeclUtils.write_execl(self.execl_f, self.sheet_table, self.count, self.audio_info, u'逻辑思维音频.xlsx')
               print('采集了{}条数据'.format(self.count))
               # 清空集合,为再次存放数据做准备
               self.audio_info = []

           time.sleep(3) # 不要请求太快, 小心查水表
           max_id = datas[-1]['publish_time_stamp']
           if self.max_id != max_id:
               self.max_id = max_id
               self.request_data()
           else:
               print('数据抓取完毕!')

           pass

       def download_mp3(self, mp3_url):
           try:
               # 补全文件目录
               mp3_path = u'D:/store/mp3/{}'.format(mp3_url.split('/')[-1])
               print(mp3_path)
               # 判断文件是否存在。
               if not os.path.exists(mp3_path):
                   # 注意这里是写入文件,要用二进制格式写入。
                   with open(mp3_path, 'wb') as f:
                       f.write(requests.get(mp3_url).content)

           except Exception as e:
               print(e)


    if __name__ == '__main__':
       d = dedao()
       d.request_data()
    展开全文
  • 校园淘二手交易APP 每一次课设都是一次进步的机会! 一、总体设计思想 通过当今互联网的大平台,考虑到大学生校园二手交易的高效性和安全性,利用目前所学的Android知识设计出此APP。主要将系统划分为以下几个模块...

    校园淘二手交易APP

    每一次课设都是一次进步的机会!

    在这次课设中,我学到了一些以前从未接触到的知识,比如如何生成验证码,如何使用腾讯开放平台注册并获取APP ID和APP KEY实现QQ互联接入,如何实现Spinner下拉列表以及实现它的点击事件,如何通过SQLite数据库实现增删改查并通过图形化工具SQLite Expert Professional查看db文件来显式的查看数据,如何通过Intent实现复杂数据的传递,如何使用Log来追踪app的运行,这些应该是我这次最大的收获。
    在这里插入图片描述
    一、总体设计思想

    通过当今互联网的大平台,考虑到大学生校园二手交易的高效性和安全性,利用目前所学的Android知识设计出此APP。主要将系统划分为以下几个模块:用户登录授权模块,具备用户注册(用户名和密码设定)、登录验证(包括用户名、密码和验证码的验证)、第三方授权功能;商品分类模块,具备将各类商品分门别类的功能;热销模块,以列表形式呈现,点击每一个子列表都会呈现具体发布信息,可以采用星级评分条进行打分并评论;发布商品模块,具备添加文字功能,可以发布具体商品信息;个人管理模块,具备修改并保存个人信息,修改密码,查看我的发布,退出登录功能;我的发布模块,具备管理我的发布信息功能,可进行手动刷新和删除操作。

    二、系统流程分析
    在这里插入图片描述
    三、各模块功能分析与设计
    在这里插入图片描述
    四、详细设计与实现

    1、数据库设计

    需要学习可参考:添加链接描述

    使用SQLite图形化工具SQLite Expert Professional查看db文件
    包含三张表:用户信息users表,商品信息iteminfo表,评论信息comments表。
    (1)用户信息users表,通过此表可定义每个用户在数据库中存储的基本信息。使用模块:用户登录授权模块、注册模块及个人信息管理模块。用七个字段分别表示用户的userId(账号)、passWord(登录密码)、name(真实姓名)、subject(所学专业)、phone(联系方式)、qq(qq号)及address(地址)。其中,设置userId为主键,passWord不能为空,如图所示:
    在这里插入图片描述
    建立脚本(基于SQLite数据库实现),代码如下:

    db.execSQL("create table if not exists users" +
            "(userId varchar(20) primary key," +
            "passWord varchar(20) not null," +
            "name varchar(20)," +
            "subject varchar(20)," +
            "phone varchar(15)," +
            "qq varchar(15)," +
            "address varchar(50))");
    

    (2)商品信息iteminfo表,通过此表可定义每条被发布的商品列表项在数据库中存储的基本信息。使用模块:商品热销模块、商品分类模块、商品信息发布模块及我的发布管理模块。用八个字段分别表示商品信息的id(商品编号)、userId(发布者ID)、title(标题)、kind(类别)、info(描述)、price(价格)、time(发布时间)及contact(联系方式)。其中,设置id为主键,如图所示:
    在这里插入图片描述
    建立脚本(基于SQLite数据库实现),代码如下:

    db.execSQL("create table if not exists iteminfo(" +
            "id integer primary key  AUTOINCREMENT," +
            "userId varchar(100)," +
            "title varchar(200)," +
            "kind varchar(100)," +
            "info varchar(1000)," +
            "price varchar(100)," +
            "time DATETIME," +
            "contact varchar(50))");
    

    (3)评论信息comments表,通过此表可定义每条评论在数据库中存储的基本信息。使用模块:商品评论模块。用五个字段分别表示userId(评论者ID)、itemId(列表项ID)、comment(评论)、textView(星级评价条打分)及time(评论时间)。不设置主键,如图所示:
    在这里插入图片描述
    建立脚本(基于SQLite数据库实现),代码如下:

    db.execSQL("create table if not exists comments(" +
            "userId varchar(100)," +
            "itemId integer," +
            "comment varchar(1000)," +
            "textView varchar(100),"+
            "time DATETIME)");
    

    2、界面设计与实现(我太喜欢做界面了hhh)

    这是我的小可爱APP图标!
    在这里插入图片描述
    <1> 欢迎界面
    在这里插入图片描述
    <2> 登录界面
    在这里插入图片描述
    <3> 第三方授权界面-QQ
    在这里插入图片描述
    <4> 注册界面
    在这里插入图片描述
    <5> 主界面-首页
    在这里插入图片描述
    <6> 商品发布界面
    在这里插入图片描述
    <7> 我的发布界面
    在这里插入图片描述
    <8> 商品分类界面-书籍(美妆、电子产品、体育用品同理)
    在这里插入图片描述
    <9> 商品评论界面
    在这里插入图片描述
    <10> 个人中心界面
    在这里插入图片描述
    <11> 个人信息界面
    在这里插入图片描述
    <12> 修改密码界面
    在这里插入图片描述
    3、主要功能模块实现

    (由于代码比较多,下面只记录重要的功能)

    <1> 用户登录授权模块
    在这里插入图片描述

    //将所输入的用户名和密码与数据库中的数据进行比较判断是否能够登陆成功
    private void checkUser(String user, String password) {
        dbhelper = new DBOpenHelper(this);
        db=dbhelper.getReadableDatabase();
        try{
            String sql="SELECT * FROM users WHERE userId=? and passWord=?";
            Cursor cursor=db.rawQuery(sql,new String[]{user,password});
            if(cursor.getCount()==0){
                Toast.makeText(getApplicationContext(), "用户名或密码错误!", Toast.LENGTH_SHORT).show();
            }
            else{
                Toast.makeText(getApplicationContext(), "登录成功", Toast.LENGTH_SHORT).show();
                Intent intent = new Intent(LoginActivity.this,MainActivity.class);
                post_userid=user;
                startActivity(intent);
            }
            cursor.close();
            db.close();
        }catch (SQLiteException e){
            Toast.makeText(getApplicationContext(), "登录失败", Toast.LENGTH_SHORT).show();
        }
    }
    //注册验证
        if (!TextUtils.isEmpty(user) && !TextUtils.isEmpty(password1) &&  !TextUtils.isEmpty(password2) && password1.equals(password2)&& phoneCode.equals(realCode)) {
            checkUser(user, password1);
        }else if(user==null||user.equals("")){
            Toast.makeText(getApplicationContext(), "请输入用户账号!", Toast.LENGTH_SHORT).show();
        }else if(password1==null||password1.equals("")){
            Toast.makeText(getApplicationContext(), "请输入密码!", Toast.LENGTH_SHORT).show();
        }else if(!password1.equals(password2)){
            Toast.makeText(getApplicationContext(), "两次输入的密码不一致!", Toast.LENGTH_SHORT).show();
        } else if(!phoneCode.equals(realCode)){
        Toast.makeText(RegisterActivity.this, "验证码错误", Toast.LENGTH_SHORT).show();
        mIvRegisteractivityShowcode.setImageBitmap(Code.getInstance().createBitmap());
        realCode = Code.getInstance().getCode().toLowerCase();
        Log.i(TAG,"realCode为"+realCode);
    }
    //检查账号是否存在
    private void checkUser(String user, String password1) {
        dbhelper = new DBOpenHelper(this);
        db=dbhelper.getReadableDatabase();
        try{
            String sql="SELECT * FROM users WHERE userId=?";
            Cursor cursor=db.rawQuery(sql,new String[]{user});
            if(cursor.getCount()>0){
                Toast.makeText(getApplicationContext(), "账号已存在!", Toast.LENGTH_SHORT).show();
            }
            else{
                ContentValues values = new ContentValues();
                //开始组装第一条数据   
    	 //账号userId,密码passWord,姓名name,专业subject,电话phone,QQ号qq,地址address
                values.put("userId",user);
                values.put("passWord",password1);
                db.insert("users",null,values);//插入第一条数据
                Toast.makeText(getApplicationContext(), "注册成功,请登录", Toast.LENGTH_SHORT).show();
                Intent intent = new Intent(RegisterActivity.this,LoginActivity.class);
                startActivity(intent);
            }
            cursor.close();
            db.close();
        }catch (SQLiteException e){
            Toast.makeText(getApplicationContext(), "注册失败", Toast.LENGTH_SHORT).show();
        }
    }
    

    实现QQ第三方授权登录的qqActivity类:

    需要学习可参考:Android实现第三方QQ登录

    public class qqActivity extends AppCompatActivity {
    
        //QQ登录申请的appid
        public static final String QQ_APP_ID = "1110228647";
        //布局控件
        private Button btnLogIn;
        private ImageView headerLogo;
        private TextView tvNickName;
        private TextView openId;
    
        //显示获取到的头像和昵称
        private Handler mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                if (msg.what == 0) {//获取昵称
                    tvNickName.setText((CharSequence) msg.obj);//String实现了CharSequence接口
                } else if (msg.what == 1) {//获取头像
                    headerLogo.setImageBitmap((Bitmap) msg.obj);
                }
            }
        };
    
        //需要腾讯提供的一个Tencent类
        private Tencent mTencent;
        //还需要一个IUiListener 的实现类(LogInListener implements IUiListener)
        private LogInListener mListener;
    
        //用来判断当前是否已经授权登录,若为false,点击登录button时进入授权,否则注销
        private boolean isLogIned = false;
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_qq);
    
            //首先需要用APP ID 获取到一个Tencent实例
            //Tencent类是SDK的主要实现类,开发者可通过Tencent类访问开放的OpenAPI
            mTencent = Tencent.createInstance(QQ_APP_ID, this.getApplicationContext());
    
            //初始化一个IUiListener对象,在IUiListener接口的回调方法中获取到有关授权的某些信息
            // (需要覆写onActivityResult方法,成功接收到回调)
            mListener = new LogInListener();
            //初始化各控件
            initView();
        }
    
        private void initView() {
            btnLogIn = (Button) findViewById(R.id.mainQQ_btn_login);
            headerLogo = (ImageView) findViewById(R.id.mainQQ_iv_user_logo);
            tvNickName = (TextView) findViewById(R.id.mainQQ_tv_user_nickname);
            openId = (TextView) findViewById(R.id.mainQQ_tv_user_openid);
    
            btnLogIn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (!isLogIned) {
                        isLogIned = true;
                        //调用QQ登录,用IUiListener对象作参数
                        if (!mTencent.isSessionValid()) {
                            mTencent.login(qqActivity.this, "all", mListener);
                        }
                    } else {
                        //调用QQ注销接口
                        mTencent.logout(qqActivity.this);
                        isLogIned = false;
                        Toast.makeText(qqActivity.this, "登录已注销!", Toast.LENGTH_SHORT).show();
                    }
                }
            });
        }
    
        //LogInListener是IUiListener的实现类,其中的回调方法用来接收授权后的相关信息
        private class LogInListener implements IUiListener{
            @Override
            public void onComplete(Object o) {
                Toast.makeText(qqActivity.this, "授权成功!", Toast.LENGTH_LONG).show();
                System.out.println("o.toString() ------------------------->        " + o.toString());
    
                JSONObject jsonObject = (JSONObject) o;
    
                //设置openid和token,否则获取不到下面的信息
                initOpenidAndToken(jsonObject);
                //获取QQ用户的各信息
                getUserInfo();
            }
    
            @Override
            public void onError(UiError uiError) {
    
                Toast.makeText(qqActivity.this, "授权出错!", Toast.LENGTH_LONG).show();
            }
    
            @Override
            public void onCancel() {
                Toast.makeText(qqActivity.this, "授权取消!", Toast.LENGTH_LONG).show();
            }
        }
    
        //登录成功后调用public void onComplete(JSONObject arg0) 回传的JsonObject, 其中包含OpenId, AccessToken等重要数据
        //{
        //"ret":0,
        //"pay_token":"xxxxxxxxxxxxxxxx",
        //"pf":"openmobile_android",
        //"expires_in":"7776000",
        //"openid":"xxxxxxxxxxxxxxxxxxx",
        //"pfkey":"xxxxxxxxxxxxxxxxxxx",
        //"msg":"sucess",
        //"access_token":"xxxxxxxxxxxxxxxxxxxxx"
        //}
        //初始化OPENID和TOKEN值(为了得到用户信息)
        private void initOpenidAndToken(JSONObject jsonObject) {
            try {
                String openid = jsonObject.getString("openid");
                openId.setText(openid);
                String token = jsonObject.getString("access_token");
                String expires = jsonObject.getString("expires_in");
    
                if (!TextUtils.isEmpty(token) && !TextUtils.isEmpty(expires)
                        && !TextUtils.isEmpty(openid)) {
                    mTencent.setAccessToken(token, expires);
                    mTencent.setOpenId(openid);
                }
    
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    
        //sdk给我们提供了一个类UserInfo,这个类中封装了QQ用户的一些信息,我们可以通过这个类拿到这些信息
        //采用同步调用方式(由于同步调用直接访问网络,是延时性操作,需要放入线程中执行)
        private void getUserInfo() {
            QQToken mQQToken = mTencent.getQQToken();
            UserInfo userInfo = new UserInfo(qqActivity.this, mQQToken);
            userInfo.getUserInfo(new IUiListener() {
                                     @Override
                                     public void onComplete(final Object o) {
                                         JSONObject userInfoJson = (JSONObject) o;
                                         //                {
    //                        "ret": 0,
    //                        "msg": "",
    //                        "is_lost": 0,
    //                        "nickname": "维他命",
    //                        "gender": "女",
    //                        "province": "天津",
    //                        "city": "滨海新区",
    //                        "figureurl": "http://qzapp.qlogo.cn/qzapp/1110228647/CB74B8982DFC8EB1ABE233BAF946435B/30",
    //                        "figureurl_1": "http://qzapp.qlogo.cn/qzapp/1110228647/CB74B8982DFC8EB1ABE233BAF946435B/50",
    //                        "figureurl_2": "http://qzapp.qlogo.cn/qzapp/1110228647/CB74B8982DFC8EB1ABE233BAF946435B/100",
    //                        "figureurl_qq_1": "http://q.qlogo.cn/qqapp/1110228647/CB74B8982DFC8EB1ABE233BAF946435B/40",
    //                        "figureurl_qq_2": "http://q.qlogo.cn/qqapp/1110228647/CB74B8982DFC8EB1ABE233BAF946435B/100",
    //                        "is_yellow_vip": "0",
    //                        "vip": "0",
    //                        "yellow_vip_level": "0",
    //                        "level": "0",
    //                        "is_yellow_year_vip": "0"
    //                }
                                         Message msgNick = new Message();
                                         msgNick.what = 0;//昵称
                                         try {
                                             msgNick.obj = userInfoJson.getString("nickname");//直接传递一个昵称的内容过去
                                         } catch (JSONException e) {
                                             e.printStackTrace();
                                         }
                                         mHandler.sendMessage(msgNick);
                                         //子线程 获取并传递头像图片,由Handler更新
                                         new Thread(new Runnable() {
                                             @Override
                                             public void run() {
                                                 Bitmap bitmapHead = null;
                                                 if (((JSONObject) o).has("figureurl")) {
                                                     try {
                                                         String headUrl = ((JSONObject) o).getString("figureurl_qq_2");
                                                         bitmapHead = Util.getbitmap(headUrl);
    
                                                     } catch (JSONException e) {
                                                         e.printStackTrace();
                                                     }
                                                     Message msgHead = new Message();
                                                     msgHead.what = 1;
                                                     msgHead.obj = bitmapHead;
                                                     mHandler.sendMessage(msgHead);
    
                                                 }
                                             }
                                         }).start();
    
                                          btnLogIn.setOnClickListener(new View.OnClickListener() {
                                              @Override
                                              public void onClick(View v) {
                                                  startActivity(new Intent(qqActivity.this,MainActivity.class));
                                                  finish();
                                              }
                                          });
    
                                     }
    
                                     @Override
                                     public void onError(UiError uiError) {
                                         Log.e("GET_QQ_INFO_ERROR", "获取qq用户信息错误");
                                         Toast.makeText(qqActivity.this, "获取qq用户信息错误", Toast.LENGTH_SHORT).show();
                                     }
    
                                     @Override
                                     public void onCancel() {
                                         Log.e("GET_QQ_INFO_CANCEL", "获取qq用户信息取消");
                                         Toast.makeText(qqActivity.this, "获取qq用户信息取消", Toast.LENGTH_SHORT).show();
                                     }
                                 }
            );
        }
    
    
        //确保能接收到回调
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            Tencent.onActivityResultData(requestCode, resultCode, data, mListener);
        }
    }
    
    

    自定义的Util类如下:

    public class Util {
        public static String TAG="UTIL";
        public static Bitmap getbitmap(String imageUri) {
            Log.v(TAG, "getbitmap:" + imageUri);
            // 显示网络上的图片
            Bitmap bitmap = null;
            try {
                URL myFileUrl = new URL(imageUri);
                HttpURLConnection conn = (HttpURLConnection) myFileUrl.openConnection();
                conn.setDoInput(true);
                conn.connect();
    
                InputStream is = conn.getInputStream();
                bitmap = BitmapFactory.decodeStream(is);
                is.close();
    
                Log.v(TAG, "image download finished." + imageUri);
            } catch (IOException e) {
                e.printStackTrace();
                Log.v(TAG, "getbitmap bmp fail---");
                return null;
            }
            return bitmap;
        }
    
    }
    

    <2> 商品热销模块
    在这里插入图片描述

    //打开数据表iteminfo查询所有数据,然后将一组数据存放在一个Map里,各组数据存放在一个ArrayList里
    dbHelper = new DBOpenHelper(this);
    db = dbHelper.getWritableDatabase();//打开数据库
    data = new ArrayList<>(); // 列表
    Cursor cursor = db.query(TABLENAME,null,null,null,null,null,null,null); // 数据库查询
    if (cursor.moveToFirst()){
        while (!cursor.isAfterLast()){
            item = new HashMap<String, Object>();  // 为列表项赋值
            item.put("id",cursor.getInt(0));
            item.put("userid",cursor.getString(1));
            item.put("title",cursor.getString(2));
            item.put("kind",cursor.getString(3));
            item.put("info",cursor.getString(4));
            item.put("price",cursor.getString(5));
            cursor.moveToNext();
            data.add(item); // 加入到列表中
        }
    }
    
    // 使用MydefineAdapter布局listview
    MydefineAdapter mydefineAdapter = new MydefineAdapter(this,R.layout.listitem,data);
    listview.setAdapter(mydefineAdapter);
    // 为列表项设置监听器
    listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            intent = new Intent(MainActivity.this, item_info.class);
            // 获取该列表项的key为id的键值,即商品的id,将其储存在Bundle传递给打开的页面
            intent.putExtra("id", data.get(position).get("id").toString()); 
            startActivity(intent);
        }
    });
    
    /*自定义适配器需继承BaseAdapter,并重写其四个方法*/
    public class MydefineAdapter extends BaseAdapter {
        private Context context;
        private ArrayList<Map<String,Object>> data;
        private int item_layout_id;
    
        public MydefineAdapter(Context context,int item_layout_id,ArrayList<Map<String,Object>> data){
            this.context=context;
            this.data=data;
            this.item_layout_id=item_layout_id;
        }
        //返回适配器要包含的数据项数量
        @Override
        public int getCount() {
            return data.size();
        }
        //返回数据集中position位置的数据对象(从0开始)
        @Override
        public Object getItem(int position) {
            return data.get(position);
        }
        //返回position位置的列表项的ID
        @Override
        public long getItemId(int position) {
            return position;
        }
        //返回position位置的绑定数据后的视图组件,其中convertview表示缓冲绘制好的视图组件,parent是convertview的父视图
        //使用view参数作为缓存进行优化,减少了重绘view的次数
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder viewHolder=null;//声明缓存布局中所有视图组件的对象引用
            //判断有无可重用的View,若无就重新绘制
            if(convertView==null){
                viewHolder=new ViewHolder();
                //LayoutInflater的作用是,将xml布局文件实例化为它对应的View对象
                convertView= LayoutInflater.from(context).inflate(item_layout_id,parent,false);
                viewHolder.title=(TextView) convertView.findViewById(R.id.title);
                viewHolder.kind=(TextView)convertView.findViewById(R.id.kind);
                viewHolder.info=(TextView)convertView.findViewById(R.id.info);
                viewHolder.price=(TextView)convertView.findViewById(R.id.price);
                convertView.setTag(viewHolder);//为view设置标签并把viewHolder存储在标签中
            }else{
                viewHolder=(ViewHolder)convertView.getTag();
            }
            Map<String,Object>item=(Map<String, Object>) getItem(position);
            viewHolder.title.setText((String)item.get("title"));
            viewHolder.kind.setText((String)item.get("kind"));
            viewHolder.info.setText((String)item.get("info"));
            viewHolder.price.setText((String)item.get("price"));
            return convertView;
        }
        //定义内部类ViewHolder减少调用findViewById
        private class ViewHolder{
            public TextView title;
            public TextView kind;
            public TextView info;
            public TextView price;
        }
    }
    //接收从上一个intent传递过来的id,把通过这个id在数据表iteminfo中查询的信息赋给相应的布局控件
    dhelper = new DBOpenHelper(this);
    db = dhelper.getWritableDatabase();
    intent = getIntent();
    initview();
    Cursor cursor = db.query("iteminfo",null,"id=?",new String[]{intent.getStringExtra("id")},null,null,null,null); // 根据接收到的id进行数据库查询
    Log.i("商品的id是",intent.getStringExtra("id"));
    if (cursor.moveToFirst()){
        while (!cursor.isAfterLast()){
            userId.setText(cursor.getString(1));
            title.setText(cursor.getString(2));
            price.setText(cursor.getString(5));
            time.setText(cursor.getString(6));
            info.setText(cursor.getString(4));
            contact.setText(cursor.getString(7));
            cursor.moveToNext();
        }
    }
    //接收从上一个intent传递过来的id,通过这个id在数据库里查询到的每一组数据存储在一个Map里,然后把所有组数据存储到一个List里
    data=new ArrayList<Map<String, Object>>(); // 列表
    Cursor cursor_ = db.query("comments",null,"itemId=?",new String[]{intent.getStringExtra("id")},null,null,null,null); // 数据库查询
    if (cursor_.moveToFirst()){
        while (!cursor_.isAfterLast()){
            item = new HashMap<String, Object>();  // 为列表项赋值
            item.put("userId",cursor_.getString(0));
            item.put("comment",cursor_.getString(2));
            item.put("textView",cursor_.getString(3));
            item.put("time",cursor_.getString(4));
            cursor_.moveToNext();
            data.add(item); // 加入到列表中
        }
    }
    /*创建RatingBar监听器 */
    chooseRatingBar.setOnRatingBarChangeListener(new RatingBar.OnRatingBarChangeListener() {
        @Override
        public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) {
            chooseRatingBar = (RatingBar) findViewById(R.id.ratingBar1);
            chooseRatingBar.setRating(rating);
            textView.setText("选择了" + rating + "个星星");
        }
    });
    //给提交评论按钮设置事件监听器
    Button submit = (Button)findViewById(R.id.submit);
    submit.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            EditText comment = (EditText)findViewById(R.id.comment);
            String submit_comment = comment.getText().toString();
            TextView textView= (TextView) findViewById(R.id.textView1);
            String star_textview=textView.getText().toString();
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss ");
            Date curDate = new Date(System.currentTimeMillis());
            String time = formatter.format(curDate);
            ContentValues values=new ContentValues();
            values.put("userId",post_userid);
            values.put("itemId",intent.getStringExtra("id"));
            values.put("comment",submit_comment);
            values.put("textView",star_textview);
            values.put("time",time);
            db.insert("comments",null,values);
            Log.i("1","评论成功");
            Toast.makeText(getApplicationContext(), "评论成功", Toast.LENGTH_SHORT).show();
            Intent intent_=new Intent(item_info.this,item_info.class);
            intent_.putExtra("id",intent.getStringExtra("id"));
            startActivity(intent_);
        }
    });
    

    <3> 商品发布+分类模块
    在这里插入图片描述

    String[] ctype;
    ctype = new String[]{"美妆", "书籍", "电子产品", "体育用品"};
    //创建一个数组适配器
    ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item,ctype);
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); //设置下拉列表框的下拉选项样式
    sp= (Spinner) super.findViewById(R.id.m1_style);
    sp.setAdapter(adapter);//将适配器添加到下拉列表上
    sp.setOnItemSelectedListener(this);
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
        kind = (sp.getSelectedItem()).toString();
    }
    public void onNothingSelected(AdapterView<?> parent) {
    }
    //给发布按钮添加事件监听器
    fabu.setOnClickListener(new View.OnClickListener() {
        @RequiresApi(api = Build.VERSION_CODES.O)
        @Override
        public void onClick(View v) {
            EditText title=(EditText)findViewById(R.id.m1_title);
            EditText price=(EditText)findViewById(R.id.m1_price);
            EditText phone=(EditText)findViewById(R.id.m1_phone);
            EditText nr=(EditText)findViewById(R.id.m1_nr);
            Date curDate = new Date(System.currentTimeMillis());
            String time = formatter.format(curDate);
            ContentValues values=new ContentValues();
            values.put("title",title.getText().toString());
            values.put("userId",post_userid);
            values.put("kind", kind);
            values.put("time",time);
            values.put("price",price.getText().toString());
            values.put("contact",phone.getText().toString());
            values.put("info",nr.getText().toString());
            db.insert("iteminfo",null,values);
            Intent intent=new Intent(AddItem.this,AddItem.class);
            Toast.makeText(getApplicationContext(), "发布成功", Toast.LENGTH_SHORT).show();
            startActivity(intent);
            finish();
        }
    });
    //将在数据库中查找的类别是“美妆”的每组数据组装成一个Map,再将所有数据存储在List里面(书籍类,电子产品类,体育用品类同理)
    dbHelper = new DBOpenHelper(this);
    db = dbHelper.getWritableDatabase();
    item = new HashMap<>();
    data = new ArrayList<>();
    Cursor cursor = db.query(TABLENAME,null,"kind=?",new String[]{"美妆"},null,null,null,null); // 数据库查询
    if (cursor.moveToFirst()){
        while (!cursor.isAfterLast()){
            item = new HashMap<String, Object>();  // 为列表项赋值
            item.put("id",cursor.getInt(0));
            item.put("userid",cursor.getString(1));
            item.put("title",cursor.getString(2));
            item.put("kind",cursor.getString(3));
            item.put("info",cursor.getString(4));
            item.put("price",cursor.getString(5));
            cursor.moveToNext();
            data.add(item); // 加入到列表中
        }
    }
    

    <4> 个人中心管理+我的发布管理模块
    在这里插入图片描述

    //获取登录时的账户账号,也就是发布者的账号,通过该账号在数据库中查询发布的商品信息
    Cursor cursor = db.query(TABLENAME,null,"userId=?",new String[]{a},null,null,null,null); // 数据库查询
    if (cursor.moveToFirst()){
        while (!cursor.isAfterLast()){
            item = new HashMap<String, Object>();  // 为列表项赋值
            item.put("id",cursor.getInt(0));
            item.put("userId",cursor.getString(1));
            item.put("title",cursor.getString(2));
            item.put("kind",cursor.getString(3));
            item.put("info",cursor.getString(4));
            item.put("price",cursor.getString(5));
            cursor.moveToNext();
            data.add(item); // 加入到列表中
        }
    }
    //长按可删除该列表项的监听器
    listview.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
        @Override
        public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
            String delId = data.get(position).get("id").toString();
            if(db.delete(TABLENAME,"id=?",new String[]{delId}) > 0) {
                Toast.makeText(getApplicationContext(), "删除成功,请刷新", Toast.LENGTH_SHORT).show();
                return true;
            }
            else {
                return false;
            }
        }
    });
    //保存修改过后的信息,将数据库中的信息更新
    private void saveValues(ContentValues values) {
        DBOpenHelper dbhelper = new DBOpenHelper(this);
        SQLiteDatabase db=dbhelper.getReadableDatabase();
        db.update("users",values,"userId=?",new String[] {id});
        db.close();
    }
    //验证用户旧密码是否输入正确,将新密码存入数据库
    private void checkpass(String oldpass, String newpass) {
        DBOpenHelper dbhelper = new DBOpenHelper(this);
        SQLiteDatabase db=dbhelper.getReadableDatabase();
        try{
            String sql="SELECT * FROM users WHERE userId=? and passWord=?";
            Cursor cursor=db.rawQuery(sql,new String[]{user,oldpass});
            if(cursor.getCount()==0){
                Toast.makeText(getApplicationContext(), "用户旧密码错误!", Toast.LENGTH_SHORT).show();
            }
            else{
                ContentValues values=new ContentValues();
                values.put("passWord",newpass);
                db.update("users",values,"userId=?",new String[] {user});
                Toast.makeText(getApplicationContext(), "修改成功", Toast.LENGTH_SHORT).show();
                Intent intent = new Intent(changepwdActivity.this,MyselfActivity.class);
                startActivity(intent);
            }
            cursor.close();
            db.close();
        }catch (SQLiteException e){
            Toast.makeText(getApplicationContext(), "修改失败", Toast.LENGTH_SHORT).show();
        }
    }
    

    fighting together!

    源码下载
    在这里插入图片描述

    展开全文
  • 得到APP产品分析

    千次阅读 2018-09-28 08:43:35
    产品是什么(客观描述:产品满足的需求及亮点等):利用碎片化的时间获得高效的知识服务; 目标用户与典型场景(目标用户使用该产品的典型场景,不少于3例): 1.目标用户:阅读爱好者,愿意为阅读而付费; ...

    产品名称:得到;

    产品是什么(客观描述:产品满足的需求及亮点等):利用碎片化的时间获得高效的知识服务;

    目标用户与典型场景(目标用户在使用该产品的典型场景,不少于3例)

        1.目标用户:阅读爱好者,愿意为阅读而付费;
    
           典型场景:小明,24岁,爱好阅读,涉猎广泛,他利用得到汲取各种观点;对于得到,他最感兴趣的是听书和电子书模块。他利用一切碎片化的时间听书或者阅读,上班路程中打开听书模块听解读人对某些书的解读,用很短的时间就可以了解到某本书的精华所在;午饭时会打开电子书模块去阅读;对于小明来说,他并不在意所听或所读的书能否带给他某方面技术的精进,他更在意的是积累,并且听书模块让他对一些自身很难去读懂的书有了更深层次的了解;       
    
        2.目标用户:只对某方面知识非常感兴趣,想找一些对应的课程进行学习;
    
           典型场景:小王,20岁,在校学生,本身学工科专业,但最近突然对人际关系方面的心理学很感兴趣,于是他上网搜索哪里可以接触到相关课程,发现了得到APP,随后他下载并在得到上搜索到了相关课程。小王的课余时间充裕,他学习完了感兴趣的课程可能还会再时不时地浏览其他的课程,但学生党对于付费课程的兴趣可能不会太高。但小王对得到还是很感兴趣,所以他仍然是潜在的付费用户;
    
        3.目标用户:对得到上讲课或直播的某个老师很感兴趣;
    
           典型场景:小华,22岁,刚进入职场的产品人,看过梁宁老师的书,觉得受益匪浅,所以开始关注梁宁老师的动态,得知梁宁老师会在得到APP上进行直播,所以下载得到并观看梁宁老师的直播;
    
        4.目标用户:想提升自己某方面的能力但又苦于没有大片时间的资深职场人;
    
           典型场景: 陈先生,35岁,某公司项目负责人,最近想在事业上更上一层楼,但平时加班严重,回家也看不了几页书来增强自己想增强的管理方面的一些知识,得到APP利用碎片化时间获得高效的知识服务的亮点正好契合了陈先生的需求,所以他利用睡觉前、上厕所、上班路上这些零散的时间来听管理方面的书;陈先生这类用户是完全不介意为想要获得的知识而花钱的;  
    

    关键功能与描述(描述关键功能名称及作用):

        1.听书:对书本的解读,可以让用户不必花大量的时间去读一本晦涩难懂的书,而是通过名家解读这样的方式让用户快速了解到书本的核心知识;这个功能相对来说比较适合那些不需要深度阅读的人;
    
        2.电子书:一些书籍的电子版,让用户不必带实体书阅读,而是换成方便的电子书;
    
        3.全部课程:又细分为能力学院、商学院、视野学院、人文学院、社科学院和科学学院,每个学院对应着相应的课程,通过课程的学习可以对某些领域进行一定的来了解;
    

    运营方法(不只是梳理运营事件,要分析运营的目的及手段):

       得到由逻辑思维团队出品,于2016年5月正式上线;
    
       1.2012年12月21日末尾逻辑思维公众号第一条开播,从那时开始,逻辑思维团队就已经积累了大量的粉丝;
    
       2.2015年11月18日,得到V1.0版本发布,得到一经出世,就打着用碎片化时间进行终身学习的理念,随后逻辑思维进驻得到APP,逻辑思维将它本身拥有的大量粉丝引进得到;
    
       3.新用户注册用0.1元即可获得7天的听书会员和优惠券,还有邀请好友注册即可获得优惠券,这些活动从一定程度上加深了用户体验,也会有刺激用户消费的作用;
    
        4.直播模块,直播模块通过一些大咖的直播内容来达到吸引用户的效果;   
    

    竞品(对比其各自的亮点):

    得到vs喜马拉雅FM

    1.页面设计:

    大体相同,但喜马拉雅FM的搜索框为透明浮动在顶部Banner之上,给人的视觉体验更好,且喜马拉雅FM有筛选和猜你喜欢模块,播放历史功能也非常方便;

    2.定位:

      喜马拉雅FM是国内最大的音频分享平台;
    
       得到是为用户提供高效终身的知识服务的平台;
    

    3.内容:

      喜马拉雅FM的的内容非常多样化,涵盖的方面很广,它的功能也更多,用户还可以上传自己的音频,所以它吸引的用户群体会更广泛。
    
       得到APP相对内容比较单一,但是它的专业性非常强,它对于内容的品质要求更严格;
    

    4.用户:

      喜马拉雅FM的用户相对广泛,它的用户大部分是以此来娱乐消磨时间,而不是想通过它去获取到什么知识;
    
     得到的专业性很强,它的目标明确,就是提供给想学知识的人一个平台,所以它的受众是十分稳定的;
    
    展开全文
  • uni-app实战专题

    2021-01-14 17:15:42
    全网最详细的uniapp实战开发app小程序课程,6大实战开发案例(社区交友,商城,即时通讯,网盘、点播、直播)帮助你获得技术优势并提高面试竞争力。 uniapp入门实战 简单、实用,立马见效的套路,助你快速上手uniapp...
  • 请从地面渠道购买本课程的教学视频: : 你还可以加入课程讨论群,与同学一起讨论问题,还可以得到我的亲自指导。 适合人群 适合有一定Vue.js和初级基础知识并且想深入学习Vue.js并使用实战项目的同学。 去做 由于...
  • 前面 本来是做 Android 开发、兼职 Unity 开发,公司有业务需求要做 iOS,还...做完后要改需求,原因是有人告知**单纯的 WebView App 发布的时候审核不会通过。**为了不蹚浑水还是直接重做吧:首页是一个全屏 Ba...
  • 手机APP应用开发技术课程论文

    千次阅读 2016-06-21 23:20:46
    1. 智能手机的发展历史 ...4. 手机APP应用开发技术课程中的知识点 1.基础的四大组件 2.sqlite数据库 3.基础布局 4.开发工具android studio和eclipse+ADT 5. 应用开发 ...
  • 没想到,又有一款新的阅读器即将发布:得到阅读器得到阅读器是由罗辑思维旗下得到APP发布的一款电纸书,与多看、掌阅一样,是基于自家的图书平台设计的硬件;如果有了解这款APP的同学,就应该清楚,得到APP与常见的...
  • 初学者福音——10个最佳APP开发入门在线学习网站

    万次阅读 多人点赞 2018-01-04 10:07:04
    根据Payscale的调查显示,现在的APP开发人员的年薪达到:$66,851。这也是为什么那么多初学的开发都想跻身到APP开发这行业的主要原因之一。每当你打开App Store时候,看着琳琅满目的APP,你肯定会被它们精致的外观和...
  • 得到APP互联网营销分析 作者:mo_daji 欢迎转载,转载请注明原出处。 原文地址:https://www.cnblogs.com/modaji/p/10630768.html 目录 一、背景介绍... 1 二、企业分析... 2 2.1基本原理... 2 2.2发展...
  • Hybrid App 开发快速指南

    万次阅读 多人点赞 2018-08-14 00:42:57
    课程背景 混合应用相对于原生应用而言,是原生应用和 Web 应用的结合体。过去几年,混合应用开发的各种利弊已得到充分的讨论和验证。关于混合应用是什么、为什么使用的问题,相信大家都有自己的答案,但如何开发混合...
  • 分析得到APP的用户年度数据后。。

    千次阅读 2018-12-16 20:11:25
    16年是知识付费元年,17至18年,知识付费开始变换。...今天早上啃着窝窝头,看见得到发布了今年的用户数据。看了一下,没想到我超过了99%的用户,我接触得到,差不多是三年前,也算是一个重度用户,不...
  • 本隐私政策部分将帮助您了解以下...6、您的个人信息如何全球范围转移 7、本隐私政策如何更新 8、如何联系我们 一、我们如何收集和使用您的信息 我们会出于本政策所述的以下目的,收集和使用您的个人信息: (...
  • “ 阅读本文大概需要 8 分钟。 ”前面我们介绍了精品连载丨安卓 App 逆向课程一之环境配置,下面我们来接着介绍一个安卓 App 逆向大杀器—— frida。前阵子受《Xposed模块...
  • 关于数字签名:产生RSA密钥对(myKeyPair),得到RSA密钥对,产生Signature对象,对用私钥对信息(info)签名,用指定算法产生签名对象,用私钥初始化签名对象,将待签名的数据传送给签名对象(须初始化之后),用公钥...
  • uni-app

    2021-11-22 22:46:19
    uni-app是什么? uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码...阿里小程序工具官方内置uni-app(详见),腾讯课堂官方为uni-app录制培训课程(详见),开发者可以放心选择。 uni-app在
  • 特此免费授予获得此软件和相关文档文件(“软件”)副本的任何人无限制地处理软件的权利,包括但不限于使用,复制,修改,合并的权利,发布,分发,再许可和/或出售本软件的副本,并允许具备软件的人员这样做,但须...
  • uni-app实战商城类app和小程序 帝莎学院创始人&CEO,目前主要从事...
  • 前后端分离架构中,服务层被拆分成了很多的微服务,服务与服务之间难免发生交互,比如:课程发布需要调用CMS服务生成静态化页面。 1、cms服务将自己注册到注册中心。 2、课程管理服务从注册中心获取cms服务...
  • 1024程序员节这一天,起步科技、高等教育出版社北京中关村图书大厦联合举办了国内第一本HTML5 App 开发专业教材——《HTML5 App 商业开发实战教程》的发布会。受邀之初,笔者其实有着些许好奇,因为行业内,...
  • uni-app 快速入门 从零开始实现新闻资讯类跨端应用(更新中) 文章目录uni-app 快速入门 从零开始实现新闻资讯类跨端应用(更新中)一、微信小程序基础1.初始化文件目录结构2.数据绑定,条件判断、列表渲染二、uni-...
  • Building an iOS Address Book ...获得本项目课程中成为iOS开发人员所需的实践经验 资深程序员John Nastos分享了构建完整iOS通讯簿应用程序的分步说明 了解如何故事板应用程序,存储和显示联系人数据,连接到其...
  • 如何开发一个App(Android)

    万次阅读 多人点赞 2018-06-20 10:52:33
    前言 本篇博客从开发的角度来介绍如何开发一个Android App,需要说明一点是,这里只是提供一个如何开发一个app的思路,并不会介绍很多技术上的细节,从整个大局去把握如何去构思一个app
  • uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到iOS、Android、H5、以及各种小程序(微信/支付宝/百度/头条/QQ/钉钉)等多个平台。 即使不跨端,uni-app同时也是更好的小程序开发...
  • 而实际情况下,针对海量用户群体的消息触达,往往面临两个比较突出的问题: 一是如何较短的时间内触达海量目标用户,实现“推得到”“推得快”和“推得准”; 二是如何根据用户的标签、分组等维度向特定的人群进行...
  • 「别开发 app 了,做个公众号就可以了」这是最近我和所有正在创业的朋友说的一句话,app 生态已经趋于饱和,低频产品已经没有开发 app 的必要,转而开发微信公众号(未来是应用号)将是最佳选择。 例如国内CMS领导...
  • 我已经使用Flutter创建了testapp。现在,我想把应用程序的名字从 "testapp"改为 “My Trips Tracker”。我该怎么做呢? 我试过从AndroidManifest.xml中更改,它被更改了,但是有Flutter提供的方法吗? A1: 有一个...
  • 相比较起来,另一个不太起眼的发布是,苹果其官方网站发布了一个mini站点(http://www.apple.com/swift/),宣传使用Swift开发的第三方App以及部分大学开设Swift课程页面中苹果表示,开发者已经开始...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 12,534
精华内容 5,013
关键字:

如何在得到app发布课程